Ordenar por campos múltiples en arrays asociativos
Una de las grandes dudas existenciales es como lograr ordenar un array de dos dimensiones por los nombres de los campos en la segunda dimension.
Un ejemplo bruto:- $a=array(
- 0=>array('id'=>1,'nombre'=>'Uno'),
- 1=>array('id'=>2,'nombre'=>'Dos')
- );
En este caso, podríamos querer ordenar las filas por la columna 'id', o la columna 'nombre'. En el fondo, lo mismo que ORDER BY en SQL.
Para los que no saben, la función uasort permite ordenar un array de acuerdo al criterio que estimemos conveniente, a través de la entrega de un callback. O sea, podríamos ordenar a mano el array por el nombre haciendo
- uasort($a,'ordenar');
- function ordenar($a,$b) {
- if ($a['nombre']>$b['nombre']) {return 1;
- } elseif ($a['nombre']<$b['nombre']) {return -1;
- } else {
- return 0; }
- }
El problema está en si queremos ordenar por múltiples campos. Por decir, primero el nombre, luego el id, o viceversa. La solución está en crear en forma dinámica el código que permita resolver el problema.
Si se dieron cuenta, la función es muy simple. Debe devolver 1 si se quiere dar a entender que el primer valor de la tupla debe ir después, -1 si debe ir antes.
Por tanto, bastaría con entregar el array y la lista de campos en un array a la función, señalando la dirección del orden (ascendente o descendente). La función debería crear en tiempo real el código necesario para ordenar, el cual se 'inyecta' en el uasort a través de la función create_function, la cual nos permite crear una función lambda o anónima, a partir de una cadena.
Basta de chachara y les muestro la función con un pequeño ejemplo
- function ordenar(&$aTabla,$aCampos) {
- $aSalida=array();
- foreach($aCampos as $sCampo=>$sOrden) {
- if($sOrden=='ASC') {
- $s1='>';
- $s2='<';
- } else {
- $s1='<';
- $s2='>';
- }
- $aSalida[]=<<<HERE
- if(array_key_exists('$sCampo',\$a)) {
- if(\$a['$sCampo'] $s1 \$b['$sCampo']) {
- return 1;
- } elseif (\$a['$sCampo'] $s2 \$b['$sCampo']) {
- return -1;
- }
- }
- HERE;
- }
- $aSalida[]='return 0;';
- uasort($aTabla, create_function('$a, $b', implode("\n",$aSalida)));
- }
- $tabla=array(
- array("nombre"=>"7-Juan Perez","direccion"=>"Aseo 100"),
- array("nombre"=>"6-Juan Perez","direccion"=>"Aseo 300"),
- array("nombre"=>"2-Juan Perez","direccion"=>"Aseo 200"),
- array("nombre"=>"1-Juan Perez","direccion"=>"Aseo 500"),
- array("nombre"=>"9-Juan Perez","direccion"=>"Aseo 900"),
- array("nombre"=>"3-Juan Perez","direccion"=>"Aseo 700"),
- array("nombre"=>"4-Juan Perez","direccion"=>"Aseo 600"),
- );
- ordenar($tabla,array("nombre"=>"ASC","direccion"=>"ASC"));
- print_r($tabla);
Ven? Nada tan terrible.Recuerden dos cosas: la tabla se envía por referencia a la función y, segundo, los campos se envían en un array asociativo, siendo la clave el campo y el valor "ASC" o "DESC"
Si algo no se entiende mucho, tiren un comentario!
- 8335 lecturas

Excelente artículo, llevaba dias con esto.
El primer ejemplo me funciona a la perfección.
El segundo ordenar por varios campos, no consigo hacer la llamada correctamente, estoy llamando a la función de esta manera:
$camnpos = array ("productid","bloqueado_desde");
uasort($arrFinal,'ordenar($camnpos)');
seguro que así no se hace , pero
¿cómo le indico en la llamda los campos por los que quiero ordenar?
gracias !
¿Cómo se llama a la función el segundo ejemplo ?
ahy que llamar con un array de argumentos ?
Arreglé el ejemplo, para que quedara claro como se llamaba a la función. espero que haya quedado claro.
Enviar un comentario nuevo