This question is intended as a reference for questions about sorting arrays in PHP. It is easy to think that your particular case is unique and worthy of a new question, but most are actually minor variations of one of the solutions on this page.
If your question is closed as a duplicate of this one, please ask for your question to be reopened only if you can explain why it differs markedly from all of the below.
如何在PHP中对数组进行排序?
如何在PHP中对复杂数组进行排序?
如何在PHP中对对象数组进行排序?
最佳答案
基本的一维数组$array = array(3, 5, 2, 8);适用的排序功能:
sort
rsort
asort
arsort
natsort
natcasesort
ksort
krsort
两者之间的区别仅在于是否保留键值关联(“a”函数),是否按从低到高或反向排序(“r”),对值或键进行排序(“k”)以及如何它比较值(“nat”与“正常”)。请参阅http://php.net/manual/en/array.sorting.php以获取概述和更多详细信息的链接。
多维数组,包括对象数组$array = array(
array('foo' => 'bar', 'baz' => 42),
array('foo' => ..., 'baz' => ...),
...
);如果要按每个条目的键“foo”对$array进行排序,则需要一个自定义比较功能。上面的sort和相关函数使用它们知道如何比较和排序的简单值。但是,PHP不会简单地“知道”如何处理像array('foo' => 'bar', 'baz' => 42)这样的复杂值。所以你需要告诉它。
为此,您需要创建一个比较功能。该函数需要两个元素,如果认为这些元素相等,则必须返回0;如果第一个值较低,则返回小于0的值;如果第一个值较高,则返回大于0的值。这就是所需要的:function cmp(array $a, array $b) {
if ($a['foo'] < $b['foo']) {
return -1;
} else if ($a['foo'] > $b['foo']) {
return 1;
} else {
return 0;
}
}通常,您将需要使用anonymous function作为回调。如果要使用方法或静态方法,请参见other ways of specifying a callback in PHP。
然后,您可以使用以下功能之一:
usort($array, 'cmp'); usort将从数组中获取两个项目,并使用它们来调用cmp函数。因此,将使用cmp()作为$a和array('foo' => 'bar', 'baz' => 42)作为另一个$b来调用array('foo' => ..., 'baz' => ...)。然后,函数返回usort中哪个值较大或它们是否相等。 usort重复此过程,为$a和$b传递不同的值,直到对数组进行排序为止。 cmp函数将被调用许多次,至少是$array中存在的值的次数,每次都会调用$a和$b的值的不同组合。
要习惯这个想法,请尝试以下操作:function cmp($a, $b) {
echo 'cmp called with $a:', PHP_EOL;
var_dump($a);
echo 'and $b:', PHP_EOL;
var_dump($b);
}您要做的就是定义一种自定义方式来比较两个项目,这就是您所需要的。这适用于各种值(value)。
顺便说一下,这适用于任何值,这些值不必是复杂的数组。如果您要进行自定义比较,则也可以对简单的数字数组进行比较。sort按引用排序,不返回任何有用的信息!
请注意,数组在适当的位置排序,您无需将返回值分配给任何东西。 $array = sort($array)将用true替换数组,而不是排序数组。只是sort($array);起作用。
自定义数字比较
如果要通过baz键(数字键)进行排序,则需要做的是:function cmp(array $a, array $b) {
return $a['baz'] - $b['baz'];
}多亏了,数学运算会返回值<0、0或> 0,具体取决于$a是小于,等于还是大于$b。
请注意,这不适用于float值,因为它们将被简化为int并失去精度。改用显式的-1,0和1返回值。
对象
如果您有一个对象数组,则其工作方式相同:function cmp($a, $b) {
return $a->baz - $b->baz;
}功能
您可以在比较函数内做任何需要的事情,包括调用函数:function cmp(array $a, array $b) {
return someFunction($a['baz']) - someFunction($b['baz']);
}弦乐
第一个字符串比较版本的快捷方式:function cmp(array $a, array $b) {
return strcmp($a['foo'], $b['foo']);
} strcmp与cmp完全一样,它返回-1,0或1。
飞船运算符(operator)
PHP 7引入了spaceship operator,它统一并简化了与跨类型比较相比相等/较小/较大的相等:function cmp(array $a, array $b) {
return $a['foo'] <=> $b['foo'];
}按多个字段排序
如果要主要按foo进行排序,但如果foo对两个元素相等,则按baz进行排序:function cmp(array $a, array $b) {
if (($cmp = strcmp($a['foo'], $b['foo'])) !== 0) {
return $cmp;
} else {
return $a['baz'] - $b['baz'];
}
}对于熟悉的人,这等效于使用ORDER BY foo, baz的SQL查询。
另请参见this very neat shorthand version和how to create such a comparison function dynamically for an arbitrary number of keys。
归类为手动的静态订单
如果要将元素按“手动顺序”排序,例如“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);
}
对于上述所有情况,如果您使用的是PHP 5.3或更高版本(确实应该使用),请对较短的代码使用匿名函数,并避免使另一个全局函数随处可见:usort($array, function (array $a, array $b) { return $a['baz'] - $b['baz']; });这就是对复杂的多维数组进行排序的简单方式。再说一遍,只需要考虑教PHP如何分辨两个项目中的哪一个“更大”即可。让PHP进行实际的排序。
同样对于以上所有内容,要在升序和降序之间进行切换,只需交换$a和$b参数即可。例如。:return $a['baz'] - $b['baz']; // ascending
return $b['baz'] - $a['baz']; // descending根据另一数组对一个数组进行排序
然后是奇特的array_multisort,它使您可以根据另一个数组对一个数组进行排序:$array1 = array( 4, 6, 1);
$array2 = array('a', 'b', 'c');这里的预期结果将是:$array2 = array('c', 'a', 'b'); // the sorted order of $array1使用array_multisort到达那里:array_multisort($array1, $array2);从PHP 5.5.0开始,您可以使用array_column从多维数组中提取一列,并对该列上的数组进行排序:array_multisort(array_column($array, 'foo'), SORT_DESC, $array);您还可以在任一方向上对多于一个的列进行排序:array_multisort(array_column($array, 'foo'), SORT_DESC,
array_column($array, 'bar'), SORT_ASC,
$array);从PHP 7.0.0开始,您还可以从对象数组中提取属性。
If you have more common cases, feel free to edit this answer.