Nesne dizisini nesne alanlarına göre sırala


514

Bu nesne dizisini nameveya alanlarından birine göre nasıl sıralayabilirim 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
        )

   ....

Yanıtlar:


699

Usort kullanın , işte kılavuzdan uyarlanmış bir örnek:

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

usort($your_data, "cmp");

Ayrıca, çağrılabilir herhangi bir ifadeyi ikinci argüman olarak kullanabilirsiniz . İşte bazı örnekler:

  • Anonim işlevleri kullanma (PHP 5.3'ten)

    usort($your_data, function($a, $b) {return strcmp($a->name, $b->name);});
  • Bir sınıfın içinden

    usort($your_data, array($this, "cmp")); // "cmp" should be a method in the class
  • Ok işlevlerini kullanma (PHP 7.4'ten)

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

Ayrıca, sayısal değerleri karşılaştırıyorsanız fn($a, $b) => $a->count - $b->count, "karşılaştır" işlevi hile yapmalıdır.


93
Bu harika, ancak sıralama işlevi çağıran işlevle aynı sınıftaysa şunu kullanmalısınız: usort ($ your_data, array ($ this, "cmp"));
rmooney

7
@rmooney Evet, ancak yalnızca bir sınıfın içindeyseniz.
cambraca

11
koymak @rmooney ilk yorumunu Yanıtınızda
Mohammad Faisal

7
Ya da karşılaştırma işleviniz karşılaştırdığınız modelinizde / nesnenizdeyse (bence daha temiz bir tasarımdır) modelinizin / nesnenize tam ad alanını şu şekilde eklemelisiniz: uasort ($ members, array ("Path \ to \ Model \ Üyeniz "," karşılaştırmakAdı "));
clauziere

3
Bu dont bana hiçbir şey sıralı, sadece en büyük ilk ve tüm dinlenme i geri dönmek
Alberto Acuña

472

Heres güzel bir şekilde kapanışları kullanarak

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

Lütfen bunun PHP belgelerinde olmadığını unutmayın, ancak 5.3'ten fazla kapak kullanıyorsanız, çağrılabilir argümanların sağlanabildiği yerlerde desteklenir.


16
Karşılaştırma işlevini hızlı bir şekilde tanımlayabildiğimiz ve bir sınıfta kullanabileceğimiz için bunu kabul edilen cevaptan daha çok seviyorum
Nam G VU

11
Eğer dizi anahtarlarını korumak istiyorsanız kullanınuasort()
gillytech

10
Sıralama için,-1 * strcmp($a->name, $b->name);
Wallace Maxters

17
Desc sıralamak için çarpmaya gerek yok. Sadece argümanları değiştirin:strcmp($b->name, $a->name)
zxcat

3
Benim gibi kabul edilen cevabın buna tercih edildiği bir durumla karşılaşabilirsiniz. Örneğin, bir ebeveyniniz ve bir alt sınıfınız olabilir. Çocuk sınıfı, kullanan bir işlevi geçersiz kılar, usortancak karşılaştırma işlevi aynıdır. Bunu kullanarak protected static, üst sınıfta yalnızca bir kez tanımlamanız gereken bir yönteme çağrı yapmak yerine kapatma kodunu çoğaltmanız gerekir.
Pere

48

Tamsayı değerlerini sıralamak istiyorsanız:

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

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

Dize ile GÜNCELLENEN aynı kayıt defterine (üst veya alt) dönüştürmeyi unutmayın

// 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);
});

44

php oop kullanıyorsanız şunları değiştirmeniz gerekebilir:

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')); 

28
usort($array, 'my_sort_function');

var_dump($array);

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

Aynı kod, countAlanla .

Hakkında daha fazla bilgi usort: http://ru2.php.net/usort

Btw, bu diziyi nereden aldın? Umarım veritabanından değil mi?


1
Aslında başarılı olup olmadığını $resultiçerir TRUEve karşılaştırmanız olmalıdır $a->name > $b->name. :)
cambraca

2
@cambraca: oh, diziyi referans olarak kabul ettiğini unutmuşum. Btw, OP koleksiyonunu hangi sırayla sıralaması gerektiğini söylemedi.
zerkms

1
evet, bu bir veritabanı :) aslında veritabanından veri alır bir fonksiyondan
Alex

3
@Alex: Neden veritabanında sıralamıyorsunuz? ORDER BY count
zerkms

1
bu daha karmaşık, çünkü bu wordpress'in standart bir fonksiyon parçası ve bir eklenti yazarken, wp dosyalarını değiştiremiyorum. Ben bir sınıf içinde kullanıyorum ve nasıl işlev adını usort geçmek için bilmiyorum çünkü create_function kullanarak örnek denedim: create_function('$a,$b', "return $a->count < $b->count;")ama ben çalıştıramazsınız :( Birkaç uyarı almak ve uyarı usort, parametre 2'nin geçerli bir geri arama olmasını bekliyor
Alex

9

Bu işlevi kullanabilirsiniz (PHP Sürümü> = 5.3'te çalışır):

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;

        });
    }
}

Misal:

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)

Kullandığım $a->{$key}ve $b->{$key}yerine $a[$key]ve $b[$key]bizim gibi kesinlikle yerine dizi üyeleri daha bu özellikleri ele, konuşma, ancak bu hala aradığım cevaptı.
SteJ

Lütfen verdiğiniz çözüm sadece basit nesneler için çalışıyor, ancak SteJ'nin düzeltmesiyle denediğim tüm nesneler dizisi için işe yaradığından @ SteJ'nin önerisini örnek kodda uygulayın
user2993145

6

Bunun gibi kullanabilirsiniz usort:

usort($array,function($first,$second){
    return strcmp($first->name, $second->name);
});

5

Burada her şey başarısız olursa başka bir çözümdür:

$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;

Bu çözüm için bir Oscar almalısınız! ))))) Teşekkür
Imeksbank

4

Burada tüm cevapların dezavantajı, statik alan adları kullanmalarıdır , bu yüzden OOP tarzında ayarlanmış bir versiyon yazdım. Alıcı yöntemlerini kullandığınız varsayılırsa, bu Sınıfı doğrudan kullanabilir ve alan adını parametre olarak kullanabilirsiniz . Muhtemelen birisi yararlı buluyor.

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;
    }
} 

3

tarihleri ​​sıralamak istiyorsan

   usort($threads,function($first,$second){
        return strtotime($first->dateandtime) < strtotime($second->dateandtime);
    });

3

Sıralamanın dayandığı alanı dinamik olarak belirlemenizi sağlayan basit bir alternatif:

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

Bu, anonim işlevlere izin veren Closure sınıfını temel alır . PHP 5.3'ten beri kullanılabilmektedir.


2

Yerel tabanlı dize karşılaştırmasına ihtiyacınız varsa, strcollyerine kullanabilirsiniz strcmp.

İlk kullanım unutmayın, setlocaleile LC_COLLATEayarlanan yerel bilgilere gerekirse.

  usort($your_data,function($a,$b){
    setlocale (LC_COLLATE, 'pl_PL.UTF-8'); // Example of Polish language collation
    return strcoll($a->name,$b->name);
  });

2

Bunu Codeigniter içinde kullanıyorsanız, yöntemleri kullanabilirsiniz:

usort($jobs, array($this->job_model, "sortJobs"));  // function inside Model
usort($jobs, array($this, "sortJobs")); // Written inside Controller.

@rmooney öneriniz için teşekkür ederim. Gerçekten bana yardımcı oluyor.


Bu Codeigniter tam olarak ne kadar spesifik?
ggdx

2

İlhamlar için teşekkürler, ayrıca harici bir $ translator parametresi eklemek zorunda kaldım

usort($listable_products, function($a, $b) {
    global $translator;
    return strcmp($a->getFullTitle($translator), $b->getFullTitle($translator));
});

1

Sadece bir alana göre sıralamanız gerekiyorsa, usortiyi bir seçimdir. Ancak, birden fazla alana göre sıralama yapmanız gerekiyorsa çözüm hızla dağınık hale gelir. Bu durumda, diziler ve nesneler için SQL benzeri sorgu sözdizimini uygulayan YaLinqo kütüphanesi * kullanılabilir. Tüm durumlar için güzel bir sözdizimi vardır:

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

Burada, '$v->count'bir kısayol function ($v) { return $v->count; }(her ikisi de kullanılabilir). Bu yöntem zincirleri yineleyicileri döndürür, ancak gerekirse ->toArray()sonuna ekleyerek diziler alabilirsiniz .

* benim tarafımdan geliştirildi


1

Nspl'deki sıralama işlevini kullanabilirsiniz :

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'));

Lütfen OP'nin yerleşik işlevlerle görünüşte çözülmüş bir tesis sağlamak için neden ek bir kütüphaneye ihtiyacı olacağını açıklayın
ggdx

1

Yardımcı program sınıfı için sahip olduğum şey bu

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

Bunu aramak:

Util::sortArrayByName($array, "array_property_name");

1

Usort'u böyle kullanabilirsiniz

Numaraya göre sıralamak istiyorsanız:

function cmp($a, $b)
{
    if ($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}

$a = array(3, 2, 5, 6, 1);

usort($a, "cmp");

Veya Abc char:

function cmp($a, $b)
{
    return strcmp($a["fruit"], $b["fruit"]);
}

$fruits[0]["fruit"] = "lemons";
$fruits[1]["fruit"] = "apples";
$fruits[2]["fruit"] = "grapes";

usort($fruits, "cmp");

Daha fazlasını görün: https://www.php.net/manual/en/function.usort.php

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.