Tableaux unidimensionnels de base
$array = array(3, 5, 2, 8);
Fonctions de tri applicables :
sort
rsort
asort
arsort
natsort
natcasesort
ksort
krsort
La différence entre les deux consiste simplement à savoir si les associations clé-valeur sont conservées (le " a
"), qu'il trie de bas en haut ou inversement (fonctions " r
"), qu'il trie les valeurs ou les clés (" k
") et comment il compare les valeurs (" nat
" vs. normal). Voir http://php.net/manual/en/array.sorting.php pour une vue d'ensemble et des liens vers des informations plus détaillées.
Tableaux multidimensionnels, y compris les tableaux d'objets
$array = array(
array('foo' => 'bar', 'baz' => 42),
array('foo' => ..., 'baz' => ...),
...
);
Si vous voulez trier $array
par la clé 'foo' de chaque entrée, vous avez besoin d'une fonction de comparaison personnalisée . Ce qui précède sort
et les fonctions connexes travaillent sur des valeurs simples qu'ils savent comparer et trier. PHP ne sait pas simplement "savoir" quoi faire avec un fichier valeur complexe como array('foo' => 'bar', 'baz' => 42)
pourtant ; il faut donc le dire.
Pour ce faire, vous devez créer un fonction de comparaison . Cette fonction prend deux éléments et doit retourner 0
si ces éléments sont considérés comme égaux, une valeur inférieure à 0
si la première valeur est inférieure et une valeur supérieure à 0
si la première valeur est supérieure. C'est tout ce qui est nécessaire :
function cmp(array $a, array $b) {
if ($a['foo'] < $b['foo']) {
return -1;
} else if ($a['foo'] > $b['foo']) {
return 1;
} else {
return 0;
}
}
Souvent, vous voudrez utiliser un fonction anonyme en tant que rappel. Si vous souhaitez utiliser une méthode ou une méthode statique, reportez-vous à l'onglet autres façons de spécifier un callback en PHP .
Vous utilisez ensuite l'une de ces fonctions :
Là encore, ils ne diffèrent que par le fait qu'ils conservent les associations clé-valeur et qu'ils trient par valeurs ou par clés. Lisez leur documentation pour plus de détails.
Exemple d'utilisation :
usort($array, 'cmp');
usort
va prendre deux éléments du tableau et appeler votre cmp
avec eux. Donc cmp()
sera appelé avec $a
como array('foo' => 'bar', 'baz' => 42)
y $b
comme un autre array('foo' => ..., 'baz' => ...)
. La fonction retourne ensuite à usort
laquelle des valeurs était la plus grande ou si elles étaient égales. usort
répète ce processus en passant différentes valeurs pour $a
y $b
jusqu'à ce que le tableau soit trié. Le site cmp
sera appelée plusieurs fois, au moins autant de fois qu'il y a de valeurs dans $array
avec différentes combinaisons de valeurs pour $a
y $b
à chaque fois.
Pour vous habituer à cette idée, essayez ceci :
function cmp($a, $b) {
echo 'cmp called with $a:', PHP_EOL;
var_dump($a);
echo 'and $b:', PHP_EOL;
var_dump($b);
}
Tout ce que vous avez fait est de définir un moyen personnalisé de comparer deux éléments, c'est tout ce dont vous avez besoin. Cela fonctionne avec toutes sortes de valeurs.
Au fait, cela fonctionne avec n'importe quelle valeur, les valeurs ne doivent pas nécessairement être des tableaux complexes. Si vous souhaitez effectuer une comparaison personnalisée, vous pouvez également le faire sur un simple tableau de chiffres.
sort
trie par référence et ne retourne rien d'utile !
Notez que le tableau trie en place vous n'avez pas besoin d'affecter la valeur de retour à quoi que ce soit. $array = sort($array)
remplacera le tableau par true
mais pas avec un tableau trié. Juste sort($array);
travaux.
Comparaisons numériques personnalisées
Si vous voulez trier par le baz
qui est numérique, tout ce que vous avez à faire est de :
function cmp(array $a, array $b) {
return $a['baz'] - $b['baz'];
}
Merci à Le PoWEr des MATHs ceci renvoie une valeur < 0, 0 ou > 0 selon que $a
est inférieur, égal ou supérieur à $b
.
Notez que cela ne fonctionnera pas bien pour float
puisqu'elles seront réduites à une valeur de int
et perdre la précision. Utilisez un langage explicite -1
, 0
y 1
à la place des valeurs de retour.
Objets
Si vous avez un tableau d'objets, cela fonctionne de la même manière :
function cmp($a, $b) {
return $a->baz - $b->baz;
}
Fonctions
Vous pouvez faire tout ce dont vous avez besoin à l'intérieur d'une fonction de comparaison, y compris appeler des fonctions :
function cmp(array $a, array $b) {
return someFunction($a['baz']) - someFunction($b['baz']);
}
Cordes
Un raccourci pour la première version de comparaison de chaînes de caractères :
function cmp(array $a, array $b) {
return strcmp($a['foo'], $b['foo']);
}
strcmp
fait exactement ce que l'on attend d'elle cmp
ici, il renvoie -1
, 0
ou 1
.
Opérateur de vaisseau spatial
PHP 7 a introduit l'option opérateur de vaisseau spatial qui unifie et simplifie les comparaisons de type égal/plus petit/plus grand :
function cmp(array $a, array $b) {
return $a['foo'] <=> $b['foo'];
}
Tri par champs multiples
Si vous voulez trier principalement par foo
mais si foo
est égale pour deux éléments triés par baz
:
function cmp(array $a, array $b) {
if (($cmp = strcmp($a['foo'], $b['foo'])) !== 0) {
return $cmp;
} else {
return $a['baz'] - $b['baz'];
}
}
Pour ceux qui sont familiers, ceci est équivalent à une requête SQL avec ORDER BY foo, baz
.
Voir aussi cette version abrégée très soignée y Comment créer dynamiquement une telle fonction de comparaison pour un nombre arbitraire de clés ? .
Triage dans un ordre manuel et statique
Si vous voulez trier les éléments dans un "ordre manuel" comme "foo", "bar", "baz" :
function cmp(array $a, array $b) {
static $order = array('foo', 'bar', 'baz');
return array_search($a['foo'], $order) - array_search($b['foo'], $order);
}
Pour tout ce qui précède, si vous utilisez PHP 5.3 ou plus (et vous devriez vraiment le faire), utilisez les fonctions anonymes pour un code plus court et pour éviter d'avoir une autre fonction globale flottant autour :
usort($array, function (array $a, array $b) { return $a['baz'] - $b['baz']; });
Voilà à quel point le tri d'un tableau multidimensionnel complexe peut être simple. Encore une fois, il suffit de penser en termes de apprendre à PHP comment dire lequel de deux éléments est le plus grand. ; laissez PHP faire le tri réel.
De même, pour tout ce qui précède, pour passer de l'ordre ascendant à l'ordre descendant, il suffit d'intervertir les paramètres suivants $a
y $b
des arguments autour. Par exemple :
return $a['baz'] - $b['baz']; // ascending
return $b['baz'] - $a['baz']; // descending
Trier un tableau en fonction d'un autre
Et puis il y a l'étrange array_multisort
qui vous permet de trier un tableau en fonction d'un autre :
$array1 = array( 4, 6, 1);
$array2 = array('a', 'b', 'c');
Le résultat attendu ici serait :
$array2 = array('c', 'a', 'b'); // the sorted order of $array1
Utilice array_multisort
pour y arriver :
array_multisort($array1, $array2);
A partir de PHP 5.5.0, vous pouvez utiliser array_column
pour extraire une colonne d'un tableau multidimensionnel et trier le tableau sur cette colonne :
array_multisort(array_column($array, 'foo'), SORT_DESC, $array);
Vous pouvez également trier sur plus d'une colonne, chacune dans un sens ou dans l'autre :
array_multisort(array_column($array, 'foo'), SORT_DESC,
array_column($array, 'bar'), SORT_ASC,
$array);
Depuis PHP 7.0.0, vous pouvez également extraire les propriétés d'un tableau d'objets.
Si vous avez des cas plus courants, n'hésitez pas à modifier cette réponse.
0 votes
@jterry Exactement, c'est pour cela que je l'ai fait, pour avoir enfin une bonne question de référence pour conclure. Répondre à chaque flocon de neige individuellement n'aide personne :)
3 votes
Je pense que les gens devraient simplement jeter un coup d'oeil à php.net.
0 votes
@Alex Ha ! Absolument. Le problème est que personne ne fait de RTFM. :D
2 votes
Nous avons déjà ces réponses, je vous suggère de lister les meilleures réponses à l'intérieur de chaque réponse ici au lieu de dupliquer (ou réécrire) le contenu. De plus, les tableaux ont tendance à être vus individuellement, donc le travail reste de fermer le vote contre les doublons dans tous les cas.
0 votes
Vous pourriez mettre un lien vers celui-ci dans le wiki des tags de la communauté, car il y a des liens vers d'autres posts avec une configuration similaire, par exemple : éviter l'injection sql, les différences d'opérateurs, etc.
1 votes
@deceze : Si personne ne fait de RTFM, personne ne fera aussi de RTFQA - les questions et réponses existantes :)
0 votes
@hakre Oui, tout cela a déjà été répondu dans un millier de cas distincts, c'est pourquoi il est pratiquement impossible de les trouver. D'où ceci. Si vous avez de bonnes réponses, n'hésitez pas à les ajouter à la réponse.
0 votes
Oui, mais à chaque fois que je rencontre une question, je connaître a été répondu des milliers de fois, il est impossible de trouver une bonne référence à laquelle se référer. Je ne m'attends pas à ce que les gens le trouvent par eux-mêmes, je veux que ce soit une référence proche.
0 votes
@hakre Je comprends où vous voulez en venir, mais la référence de l'erreur est un peu différente, je pense. Pour le tri, il suffit de comprendre une fois ; je pense que cela fonctionne mieux avec une seule réponse cohérente expliquant les différents angles. La décomposition en plusieurs réponses distinctes rendrait chacune d'entre elles plus difficile à comprendre, selon moi.
0 votes
@dat Cela montre d'autant plus à quel point une référence canonique est nécessaire, s'il y a déjà plusieurs couches de questions qui pointent ici. Si vous avez une idée particulière d'amélioration à partager, vous devriez en parler à Meta.SO.