Trier 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
)
....
17 réponses
Use usort , Voici un exemple adapté du manuel:
function cmp($a, $b)
{
return strcmp($a->name, $b->name);
}
usort($your_data, "cmp");
modifications importées à partir des commentaires:
Si vous triez le tableau à 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"))
Voici une meilleure façon d'utiliser des fermetures
usort($your_data, function($a, $b)
{
return strcmp($a->name, $b->name);
});
Veuillez noter que ce n'est pas dans la documentation de PHP mais si vous utilisez 5.3+ closures sont pris en charge où les arguments appelables peuvent être fournis.
Si vous utilisez php oop, vous devrez peut-être changer pour:
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'));
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 count
champ.
Plus de détails sur usort
: http://ru2.php.net/usort
Btw, d'où Avez-vous eu ce tableau? J'espère que pas de base de données?
Si vous voulez 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;
});
Mise à jour avec la chaîne, n'oubliez pas de convertir au 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);
});
Vous pouvez utiliser cette fonction (fonctionne en version 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;
});
}
}
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)
Vous pouvez utiliser usort
, comme ceci:
usort($array,function($first,$second){
return strcmp($first->name, $second->name);
});
L'inconvénient de toutes les réponses ici est qu'elles utilisent des noms de champsstatiques , donc j'ai écrit une version ajustée dans le style POO. Supposé que vous utilisez des méthodes getter, vous pouvez utiliser directement cette classe et utiliser le nom de Champ comme paramètre . Probablement quelqu'un le trouve 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;
}
}
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;
Si vous avez besoin d'une comparaison de chaînes locale, vous pouvez utiliser strcoll
au lieu de strcmp
.
Rappelez-vous la première utilisation setlocale
avec LC_COLLATE
pour définir les paramètres régionaux d'information 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);
});
Si vous utilisez ceci dans Codeigniter, vous pouvez utiliser les méthodes:
usort($jobs, array($this->job_model, "sortJobs")); // function inside Model
usort($jobs, array($this, "sortJobs")); // Written inside Controller.
@rmooney merci pour la suggestion. Ça m'aide vraiment.
Merci pour les inspirations, j'ai aussi dû ajouter un paramètre externe $ translator
usort($listable_products, function($a, $b) {
global $translator;
return strcmp($a->getFullTitle($translator), $b->getFullTitle($translator));
});
Une alternative simple qui vous permet de déterminer dynamiquement le champ sur lequel le tri est basé:
$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 de fermeture , qui permet des fonctions anonymes. Il est disponible depuis PHP 5.3.
Si vous avez besoin de trier par un seul champ, puis usort
est un bon choix. Cependant, la solution devient rapidement désordonnée si vous devez Trier par plusieurs champs. Dans ce cas, yalinqo library * peut être utilisé, ce 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');
Ici '$v->count'
est un raccourci pour function ($v) { return $v->count; }
(peuvent être utilisés). Ces chaînes de méthodes renvoient des itérateurs, mais vous pouvez obtenir des tableaux en ajoutant ->toArray()
à la fin si vous en avez besoin il.
* développé par moi
Vous pouvez utiliser triés la 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'));
Si vous voulez trier les dates
usort($threads,function($first,$second){
return strtotime($first->dateandtime) < strtotime($second->dateandtime);
});
C'est Ce que j'ai pour une classe utilitaire
class Util
{
public static function sortArrayByName(&$arrayToSort, $meta) {
usort($arrayToSort, function($a, $b) use ($meta) {
return strcmp($a[$meta], $b[$meta]);
});
}
}
Appelez-le:
Util::sortArrayByName($array, "array_property_name");