Sortuj tablicę obiektów według pól obiektu

Jak mogę posortować tablicę obiektów według jednego z jej pól, np. name lub 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
        )

   ....
Author: Alex, 2010-11-26

17 answers

Użyj usort, Oto przykład zaadaptowany z podręcznika:

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

usort($your_data, "cmp");

edycje importowane z komentarzy:

Jeśli sortujesz tablicę z wewnątrz klasy i twoja funkcja sortowania cmp jest również zdefiniowana wewnątrz klasy, użyj tego:

usort($your_data, array($this, "cmp"))
 557
Author: cambraca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-16 23:25:26

Heres ładniejszy sposób za pomocą zamknięć

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

Proszę zauważyć, że nie jest to w dokumentacji PHP, ale jeśli używasz 5.3+ closures są obsługiwane, gdzie można podać wywoływalne argumenty.

 407
Author: Scott Quinlan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-15 04:31:17

Jeśli używasz php oop, być może będziesz musiał zmienić na:

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')); 
 38
Author: Doron Segal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-10 11:38:19
usort($array, 'my_sort_function');

var_dump($array);

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

Ten sam kod będzie z polem count.

Więcej szczegółów na temat usort: http://ru2.php.net/usort

Btw, skąd wzięłaś tę tablicę? Mam nadzieję, że nie z bazy danych?

 23
Author: zerkms,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-26 03:58:15

Jeśli chcesz sortować wartości całkowite:

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

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

Aktualizacja za pomocą łańcucha nie zapomnij przekonwertować do tego samego rejestru (górnego lub dolnego)

// 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);
});
 23
Author: Roman Yakoviv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-17 11:32:24

Możesz użyć tej funkcji (działa w PHP Wersja >= 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;

        });
    }
}

Przykład:

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)
 8
Author: PoengAlex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-20 13:40:04

Możesz użyć usort, TAK:

usort($array,function($first,$second){
    return strcmp($first->name, $second->name);
});
 3
Author: Luca C.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-20 09:04:58

Minusem wszystkich odpowiedzi jest to, że używająstatic nazw pól, więc napisałem poprawioną wersję w stylu OOP. Zakładając, że używasz metod getter, możesz bezpośrednio użyć tej klasy i użyć nazwy pola jako parametru . Pewnie komuś się przyda.

class CustomSort{

    public $field = '';

    public function cmp($a, $b)
    {
        /**
         * field for order is in a class variable $field
         * using getter function with naming convention getVariable() we set first letter to uppercase
         * we use variable variable names - $a->{'varName'} would directly access a field
         */
        return strcmp($a->{'get'.ucfirst($this->field)}(), $b->{'get'.ucfirst($this->field)}());
    }

    public function sortObjectArrayByField($array, $field)
    {
        $this->field = $field;
        usort($array, array("Your\Namespace\CustomSort", "cmp"));;
        return $array;
    }
} 
 2
Author: Horst Jahns,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-20 17:33:03

Jeśli wszystko zawiedzie tutaj jest inne rozwiązanie:

$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;
 2
Author: Adrian P.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-22 17:48:04

Jeśli potrzebujesz lokalnego porównania łańcuchów, możesz użyć strcoll zamiast strcmp.

Pamiętaj o pierwszym użyciu setlocale z LC_COLLATE, Aby ustawić informacje lokalne w razie potrzeby.

  usort($your_data,function($a,$b){
    setlocale (LC_COLLATE, 'pl_PL.UTF-8'); // Example of Polish language collation
    return strcoll($a->name,$b->name);
  });
 1
Author: Wilq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-05 12:51:16

Jeśli używasz tego wewnątrz Codeigniter, możesz użyć metod:

usort($jobs, array($this->job_model, "sortJobs"));  // function inside Model
usort($jobs, array($this, "sortJobs")); // Written inside Controller.
@Rmooney dziękuję za sugestię. To mi naprawdę pomaga.
 1
Author: PHP Developer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-06 09:31:37

Dzięki za inspiracje, musiałem też dodać zewnętrzny parametr $ translator

usort($listable_products, function($a, $b) {
    global $translator;
    return strcmp($a->getFullTitle($translator), $b->getFullTitle($translator));
});
 1
Author: michalzuber,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-07 14:39:30

Prosta alternatywa pozwalająca na dynamiczne określenie pola, na którym opiera się sortowanie:

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

Jest to oparte na klasie zamknięcia , która umożliwia funkcje anonimowe. Jest on dostępny od PHP 5.3.

 1
Author: clami219,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-29 16:18:55

Jeśli musisz sortować tylko po jednym polu, to usort jest dobrym wyborem. Jednak rozwiązanie szybko staje się niechlujne, jeśli trzeba sortować według wielu pól. W tym przypadku można użyć biblioteki yalinqo, która implementuje podobną do SQL składnię zapytań dla tablic i obiektów. Ma ładną składnię dla wszystkich przypadków:

$sortedByName         = from($objects)->orderBy('$v->name');
$sortedByCount        = from($objects)->orderBy('$v->count');
$sortedByCountAndName = from($objects)->orderBy('$v->count')->thenBy('$v->name');

Tutaj, '$v->count' jest skrótem function ($v) { return $v->count; } (można użyć dowolnego z nich). Te łańcuchy metod zwracają Iteratory, ale można uzyskać tablice, dodając ->toArray() na końcu, jeśli potrzebujesz to.

* opracowany przeze mnie

 0
Author: Athari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-04 00:58:14

Możesz użyć sortowanej funkcji z Nspl :

use function \nspl\a\sorted;
use function \nspl\op\propertyGetter;
use function \nspl\op\methodCaller;

// Sort by property value
$sortedByCount = sorted($objects, propertyGetter('count'));

// Or sort by result of method call
$sortedByName = sorted($objects, methodCaller('getName'));
 0
Author: Ihor Burlachenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-24 20:39:30

Jeśli chcesz sortować daty

   usort($threads,function($first,$second){
        return strtotime($first->dateandtime) < strtotime($second->dateandtime);
    });
 0
Author: Nicolas Giszpenc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-19 20:24:36

To jest to, co mam dla klasy użytkowej

class Util
{
    public static function sortArrayByName(&$arrayToSort, $meta) {
        usort($arrayToSort, function($a, $b) use ($meta) {
            return strcmp($a[$meta], $b[$meta]);
        });
    }
}

Call it:

Util::sortArrayByName($array, "array_property_name");
 0
Author: Demodave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-27 17:26:57