web-dev-qa-db-fra.com

Trier un tableau d'objets par champs d'objet

Comment puis-je trier ce tableau d'objets par l'un de ses champs, comme name ou 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
        )

   ....
444
Alex

Utilisez usort , voici un exemple adapté du manuel:

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

usort($your_data, "cmp");

éditions importées des commentaires:

Si vous triez le tableau de l'intérieur de la classe et que votre fonction de tri cmp est également définie à l'intérieur de la classe, utilisez ceci:

usort($your_data, array($this, "cmp"))
584
cambraca

Voici un moyen plus agréable d'utiliser des fermetures

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

Veuillez noter que ceci ne se trouve pas dans la documentation de PHP, mais si vous utilisez 5.3 +, les fermetures sont prises en charge et vous pouvez fournir des arguments appelables.

428
Scott Quinlan

si vous utilisez php oop, vous devrez peut-être passer à:

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')); 
39
Doron Segal

Si vous souhaitez trier les valeurs entières:

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

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

UPDATED avec la chaîne ne pas oublier de convertir dans le même registre (supérieur ou inférieur)

// 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);
});
31
Roman Yakoviv
usort($array, 'my_sort_function');

var_dump($array);

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

Le même code sera avec le champ count.

Plus de détails sur usort: http://ru2.php.net/usort

Btw, où avez-vous obtenu ce tableau? J'espère que pas de base de données?

25
zerkms

Vous pouvez utiliser cette fonction (fonctionne sous PHP Version> = 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;

        });
    }
}

Exemple:

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
PoengAlex

Vous pouvez utiliser usort, comme ceci:

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

Si tout échoue, voici une autre solution:

$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
Adrian P.

L’inconvénient de toutes les réponses ici est qu’elles utilisent les noms static field, j’ai donc écrit une version ajustée dans le style OOP. En supposant que vous utilisez des méthodes getter, vous pouvez directement utiliser cette classe et utiliser le nom du champ en tant que paramètre . Probablement que quelqu'un trouve cela utile.

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
Horst Jahns

Une alternative simple qui vous permet de déterminer dynamiquement le champ sur lequel est basé le tri:

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

Ceci est basé sur la classe Closure , qui autorise les fonctions anonymes. Il est disponible depuis PHP 5.3.

1
clami219

Merci pour les inspirations, je devais aussi ajouter un paramètre externe du traducteur

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

Si vous avez besoin d'une comparaison de chaînes locale, vous pouvez utiliser strcoll au lieu de strcmp.

N'oubliez pas d'utiliser d'abord setlocale with LC_COLLATE pour définir les informations de paramètres régionaux, si nécessaire.

  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
Wilq

Si vous utilisez ceci dans Codeigniter, vous pouvez utiliser les méthodes suivantes:

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

@rmooney merci pour la suggestion. Cela m'aide vraiment.

1
PHP Developer

C'est ce que j'ai pour une classe d'utilitaire

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

Appeler:

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

Si vous avez besoin de trier par un seul champ, alors usort est un bon choix. Cependant, la solution devient vite compliquée si vous devez trier plusieurs champs. Dans ce cas, vous pouvez utiliser YaLinqo library *, qui implémente une syntaxe de requête de type SQL pour les tableaux et les objets. Il a une jolie syntaxe pour tous les cas:

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

'$v->count' est ici un raccourci pour function ($v) { return $v->count; } (l'un ou l'autre peut être utilisé). Ces chaînes de méthodes renvoient des itérateurs, mais vous pouvez obtenir des tableaux en ajoutant finalement ->toArray() si vous en avez besoin.

* développé par moi

0
Athari

le meilleur moyen simple est

return array_values(array_sort($array, function ($value) {
  return $value->key;
}));

Remplacez la clé par la clé que vous souhaitez commander

0
Diego Salguero

si vous voulez trier les dates

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

Vous pouvez utiliser trié fonction de 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
Ihor Burlachenko

Vous pouvez utiliser usort comme ceci

Si vous souhaitez trier par numéro:

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

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

usort($a, "cmp");

ou 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");

Voir plus: https://www.php.net/manual/en/function.usort.php

0
Alex