Ordenar matriz de objetos por una propiedad

7 minutos de lectura

avatar de usuario
Alex

¿Cómo puedo ordenar esta matriz de objetos por uno de sus campos, como name o count?

Array
(
    [0] => stdClass Object
        (
            [ID] => 1
            [name] => Mary Jane
            [count] => 420
        )

    [1] => stdClass Object
        (
            [ID] => 2
            [name] => Johnny
            [count] => 234
        )

    [2] => stdClass Object
        (
            [ID] => 3
            [name] => Kathy
            [count] => 4354
        )

   ....

  • Es count o name variable/dinámico? ¿O es estáticamente “conocido” por el desarrollador?

    – mickmackusa

    1 de julio a las 15:03

avatar de usuario
cambraça

Usar usortaquí hay un ejemplo adaptado del manual:

function cmp($a, $b) {
    return strcmp($a->name, $b->name);
}

usort($your_data, "cmp");

También puedes usar cualquier invocable como segundo argumento. Aquí hay unos ejemplos:

  • Usando funciones anónimas (desde PHP 5.3)

      usort($your_data, function($a, $b) {return strcmp($a->name, $b->name);});
    
  • Desde dentro de una clase

      usort($your_data, array($this, "cmp")); // "cmp" should be a method in the class
    
  • Usando funciones de flecha (desde PHP 7.4)

      usort($your_data, fn($a, $b) => strcmp($a->name, $b->name));
    

Además, si está comparando valores numéricos, fn($a, $b) => $a->count - $b->count ya que la función “comparar” debería funcionar, o, si desea otra forma de hacer lo mismo, a partir de PHP 7 puede usar el Operador de nave espacialcomo esto: fn($a, $b) => $a->count <=> $b->count.

  • Esto es genial, pero si la función de clasificación está en la misma clase que la función de llamada, debe usar: usort($your_data, array($this, “cmp”));

    – rmooney

    20/09/2013 a las 20:53

  • @rmooney Sí, pero solo si estás dentro de una clase.

    – cambraca

    20/09/2013 a las 22:37

  • pon el primer comentario de @rmooney en tu respuesta

    – Mohammad Faisal

    18 de febrero de 2014 a las 12:57

  • O si su función de comparación está en su modelo/objeto que está comparando (que es un diseño más limpio en mi opinión), debe incluir el espacio de nombres completo para su modelo/objeto de esta manera: uasort($members, array(“Path\to \su\Modelo\Miembro”, “compararPorNombre”));

    – clauziere

    04/04/2014 a las 19:04


  • esto no me devuelve nada ordenado, solo lo más grande primero, y todo lo demás lo desclasifico

    –Alberto Acuña

    22 de octubre de 2016 a las 12:21

Aquí hay una forma más agradable de usar los cierres.

usort($your_data, function($a, $b)
{
    return strcmp($a->name, $b->name);
});

Tenga en cuenta que esto no está en la documentación de PHP, pero si usa 5.3+, los cierres son compatibles donde se pueden proporcionar argumentos invocables.

  • Me encanta esta mejor que la respuesta aceptada, ya que podemos definir rápidamente la función de comparación y usarla en una clase.

    – Nam G VU

    1 de mayo de 2012 a las 18:43

  • Si desea conservar las claves de matriz, use uasort()

    – gillytech

    1 de mayo de 2015 a las 0:36

  • Para ordenar desc, -1 * strcmp($a->name, $b->name);

    -Wallace Maxters

    14 de julio de 2015 a las 13:59

  • No es necesario multiplicar para ordenar desc. Solo intercambia argumentos: strcmp($b->name, $a->name)

    – zxcat

    19 de marzo de 2016 a las 0:53

  • Puede encontrar una situación, como yo, donde la respuesta aceptada es preferible a esta. Por ejemplo, puede tener una clase principal y una secundaria. La clase secundaria anula una función que usa usort pero la función de comparación es la misma. Al usar esto, necesitaría duplicar el código para el cierre en lugar de hacer una llamada a un protected static método que necesitaría definir solo una vez en la clase principal.

    – Padre

    28 de septiembre de 2016 a las 15:12

avatar de usuario
romano yakoviv

Si desea ordenar valores enteros:

// Desc sort
usort($array,function($first,$second){
    return $first->number < $second->number;
});

// Asc sort
usort($array,function($first,$second){
    return $first->number > $second->number;
});

ACTUALIZADO
con la cadena no olvide convertir al mismo registro (superior o inferior)

// Desc sort
usort($array,function($first,$second){
    return strtolower($first->text) < strtolower($second->text);
});

// Asc sort
usort($array,function($first,$second){
    return strtolower($first->text) > strtolower($second->text);
});

  • Para mí, $first->number no funcionó. Necesitaba usar $primero[“number”] en cambio.

    – Androidz

    19 de junio de 2021 a las 15:45

  • En lugar de usar strtolower()puede comparar cadenas e ignorar mayúsculas y minúsculas con PHP nativo strcasecmp() función (Leer PHP: strcasecmp – Manual)

    – Zoup

    16 de agosto de 2021 a las 15:09

avatar de usuario
Doron Segal

si está utilizando php oop, es posible que deba cambiar a:

public static function cmp($a, $b) 
{
    return strcmp($a->name, $b->name);
}

//in this case FUNCTION_NAME would be cmp
usort($your_data, array('YOUR_CLASS_NAME','FUNCTION_NAME')); 

avatar de usuario
zerkms

usort($array, 'my_sort_function');

var_dump($array);

function my_sort_function($a, $b)
{
    return $a->name < $b->name;
}

El mismo código será con el count campo.

Más detalles sobre usort: http://ru2.php.net/usort

Por cierto, ¿de dónde sacaste esa matriz? Espero que no de la base de datos?

  • Realmente $result contendrá TRUE si tiene éxito, y su comparación debería ser $a->name > $b->name. 🙂

    – cambraca

    26 de noviembre de 2010 a las 3:56

  • @cambraca: oh, olvidé que acepta matriz por referencia. Por cierto, OP no dijo qué orden necesita para ordenar la colección.

    – zerkms

    26 de noviembre de 2010 a las 3:57

  • bueno, sí, es una base de datos 🙂 en realidad de una función que obtiene los datos de la base de datos

    – Alex

    26 de noviembre de 2010 a las 4:01


  • @Alex: ¿por qué no lo ordenas en la base de datos entonces? ORDER BY count

    – zerkms

    26 de noviembre de 2010 a las 4:02

  • es más complicado, porque esa es una función estándar de wordpress, y como estoy escribiendo un complemento, no puedo cambiar los archivos wp. Probé tu ejemplo usando create_function (porque lo estoy usando dentro de una clase y no sé cómo pasar el nombre de la función a usort): create_function('$a,$b', "return $a->count < $b->count;") pero no puedo hacer que funcione 🙁 recibo algunos avisos y advierto que usort espera que el parámetro 2 sea una devolución de llamada válida

    – Alex

    26 de noviembre de 2010 a las 4:11


Puede usar esta función (funciona en la versión de PHP> = 5.3):

function sortArrayByKey(&$array,$key,$string = false,$asc = true){
    if($string){
        usort($array,function ($a, $b) use(&$key,&$asc)
        {
            if($asc)    return strcmp(strtolower($a{$key}), strtolower($b{$key}));
            else        return strcmp(strtolower($b{$key}), strtolower($a{$key}));
        });
    }else{
        usort($array,function ($a, $b) use(&$key,&$asc)
        {
            if($a[$key] == $b{$key}){return 0;}
            if($asc) return ($a{$key} < $b{$key}) ? -1 : 1;
            else     return ($a{$key} > $b{$key}) ? -1 : 1;

        });
    }
}

Ejemplo:

sortArrayByKey($yourArray,"name",true); //String sort (ascending order)
sortArrayByKey($yourArray,"name",true,false); //String sort (descending order)
sortArrayByKey($yourArray,"id"); //number sort (ascending order)
sortArrayByKey($yourArray,"count",false,false); //number sort (descending order)

  • Realmente $result contendrá TRUE si tiene éxito, y su comparación debería ser $a->name > $b->name. 🙂

    – cambraca

    26 de noviembre de 2010 a las 3:56

  • @cambraca: oh, olvidé que acepta matriz por referencia. Por cierto, OP no dijo qué orden necesita para ordenar la colección.

    – zerkms

    26 de noviembre de 2010 a las 3:57

  • bueno, sí, es una base de datos 🙂 en realidad de una función que obtiene los datos de la base de datos

    – Alex

    26 de noviembre de 2010 a las 4:01


  • @Alex: ¿por qué no lo ordenas en la base de datos entonces? ORDER BY count

    – zerkms

    26 de noviembre de 2010 a las 4:02

  • es más complicado, porque esa es una función estándar de wordpress, y como estoy escribiendo un complemento, no puedo cambiar los archivos wp. Probé tu ejemplo usando create_function (porque lo estoy usando dentro de una clase y no sé cómo pasar el nombre de la función a usort): create_function('$a,$b', "return $a->count < $b->count;") pero no puedo hacer que funcione 🙁 recibo algunos avisos y advierto que usort espera que el parámetro 2 sea una devolución de llamada válida

    – Alex

    26 de noviembre de 2010 a las 4:11


Si todo falla aquí hay otra solución:

$names = array(); 
foreach ($my_array as $my_object) {
    $names[] = $my_object->name; //any object field
}

array_multisort($names, SORT_ASC, $my_array);

return $my_array;

  • SORT_ASC es la dirección predeterminada y se puede omitir de forma segura.

    – mickmackusa

    1 de julio a las 14:32

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad