Los arrays indexados se pueden ordenar de forma bastante fácil utilizando directamente algunas de las funciones que PHP nos ofrece para hacerlo. ¿Y que pasa con los array multidimensionales?

Si miras el siguiente código, verás un array multidimensional en el que cada uno de los elementos es también un array con dos elementos: nombre y orden.

En el elemento “orden” se almacena la posición deseada de cada elemento. Nota como la secuencia en el código no se corresponde con este “orden” deseado. Se hace necesario que re-ordenemos este array multidimensional según el valor “orden” de cada uno de sus elementos.

$array = array (
    "elemento-1" => array (
            "nombre" => "Elemento 1",
            "orden"  => 3
        ),

    "elemento-2" => array (
            "nombre" => "Elemento 2",
            "orden"  => 2
        ),

    "elemento-3" => array (
            "nombre" => "Elemento 3",
            "orden"  => 4
        ),

    "elemento-4" => array (
            "nombre" => "Elemento 4",
            "orden"  => 1
        )
);

Métodos y alternativas

PHP nos ofrece un amplio surtido de funciones destinadas a ordenar arrays y listas para ser usadas. Puedes ver la lista completa en el manual de Ordenación de arrays.

De toda esa lista, hay funciones que ordenan por valor, otras por clave, otras que mantienen las claves, otras que no, etc, incluso hay una función que puede ordenar array multidimensionales, como array_multisort().

Pero esa función lo que hace es ordenar los elementos de cada array secundario y lo que nosotros queremos es ordenar los elementos del array primario según el valor de un elemento de los arrays secundarios, que es algo bien distinto, espero que entiendas la diferencia.

Así que array_multisort() no nos vale. La función que mejor nos va es usort() (acrónimo de user defined sort), pues permite ordenar el array por sus valores pero utilizando una función de comparación definida el usuario, es decir, por nosotros 🙋.

La función usort() se utiliza pasando el array que queremos ordenar y el nombre de la función de comparación que se utilizará. PHP pasará a esta función dos parámetros, $a y $b, siendo cada uno un elemento del array, en nuestro caso $a y $b son a su vez arrays, arrays secundarios.

Por ejemplo, podemos llamar a esta función sort_by_orden():

usort($array, 'sort_by_orden');
function sort_by_orden ($a, $b) {
    return $a['orden'] - $b['orden'];
}

En el ejemplo anterior, dentro de la función sort_by_orden() comparamos el valor del campo “orden” de que cada array secundario. El resultado de la diferencia entre ambos nos va dando la posición que debe ocupar cada elemento según el valor ascendente del campo “orden”. Puedes hacer cualquier otra comparación que desees o que necesites.

Pero hay problema, la función usort() elimina todas las claves existentes del array original.

Si vemos como queda nuestro array después de aplicar el usort() anterior veremos que los array secundarios están correctamente ordenados pero han perdido su clave (“elemento-1”, “elemento-2”, etc), que han sido sustituidas por las claves de indexación estándar:

Array
(
    [0] => Array
        (
            [nombre] => Elemento 4
            [orden] => 1
        )

    [1] => Array
        (
            [nombre] => Elemento 2
            [orden] => 2
        )

    [2] => Array
        (
            [nombre] => Elemento 1
            [orden] => 3
        )
    [3] => Array
        (
            [nombre] => Elemento 3
            [orden] => 4
        )
)

Si las claves son necesarias y no quieres perderlas deberás utilizar la función uasort(), que funciona de forma similar pero manteniendo las claves:

uasort($array, 'sort_by_orden');
function sort_by_orden ($a, $b) {
    return $a['orden'] - $b['orden'];
}

Ahora el resultado será:

Array
(
    [elemento-4] => Array
        (
            [nombre] => Elemento 4
            [orden] => 1
        )

    [elemento-2] => Array
        (
            [nombre] => Elemento 2
            [orden] => 2
        )

    [elemento-1] => Array
        (
            [nombre] => Elemento 1
            [orden] => 3
        )
    [elemento-3] => Array
        (
            [nombre] => Elemento 3
            [orden] => 4
        )
)
  • Jon Nuevo

    Muy buen post

  • Sebastian Sperandio

    Para ordenar por algun campo que contiene string podemos usar la funcion strcmp() de php:

    uasort($barrios, 'ordename');
    function ordename ($a, $b) {
    return strcmp ($a['nombre_ciudad'] , $b['nombre_ciudad'] );
    }

    • Interesante, pero hay que estar seguro de que los valores son strings, de lo contrario el resultado es bastante impredecible.

    • Wasakaca

      Hola Sebastian, una pregunta Sebastian, como harias para ordenar un array que tiene varios niveles de monto mayor a menor y menor a mayor? por ejemplo:

      
      Array
      (
          [0] => Array
              (
                  [recPriceInfo] => Array
                      (
                          [monetaryDetail] => Array
                              (
                                  [0] => Array
                                      (
                                          [monto] => 343941.87
                                      )
      
                               )
                      )
          [1] => Array
              (
                  [recPriceInfo] => Array
                      (
                          [monetaryDetail] => Array
                              (
                                  [0] => Array
                                      (
                                          [monto] => 196911.87
                                      )    
                               )
                      )
         [2] => Array
              (
                  [recPriceInfo] => Array
                      (
                          [monetaryDetail] => Array
                              (
                                  [0] => Array
                                      (
                                          [monto] => 240882.87
                                      )       
                               )
                      )
      
             )
      )
      
    • Sebastian Sperandio

      Deberia funcionar la solucion de Juan y todo lo que describe en este buen post.
      agregandole a la funcion sort_by_orden el indice correcto al campo que vas a utilizar para ordenar.

      uasort($array, 'sort_by_orden');
      function sort_by_orden ($a, $b) {
          return $a['recPriceInfo']['monetaryDetail']['monetaryDetail']['0']['monto'] - $b['recPriceInfo']['monetaryDetail']['monetaryDetail']['0']['monto'];
      }

      De todas maneras buscaría la forma de mejorar ese array, para que quede mas fácil de usar.

      Podés crear otro array nuevo y guardar solo los montos, para poder usar la funcion como lo explica Juan