Menu

PHP 数组排序:sort()、usort()、asort() 和 ksort()

sort($array) 原地排序一个列表,asort 和 ksort 按值或按键给关联数组排序,usort 用你自己的比较函数排序。本文讲解所有这些函数,教你按某一列给多维数组排序,并避开经典的 $sorted = sort($arr) 错误。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

sort($array) 原地把数组按升序排序。它会修改你传入的变量并返回 true,所以要把它单独写成一行,然后再使用这个数组。rsort() 按降序排序。

对于“按值还是按键”“升序还是降序”“保留键还是不保留”的每一种组合,PHP 都有对应的排序函数:

函数排序依据顺序键
sort值升序重新编号为 0, 1, 2
rsort值降序重新编号
asort值升序保留
arsort值降序保留
ksort键升序保留
krsort键降序保留
usort你的函数由你决定重新编号
uasort你的函数由你决定保留
uksort你作用于键的函数由你决定保留

按值给关联数组排序

对关联数组调用 sort() 会丢掉键。用 asort() 按值排序,并让每个键和它的值保持对应;用 arsort() 则把最大的排在最前面。

用 ksort 按键给数组排序

ksort() 按键排序,krsort() 按键倒序排序。在输出设置项或以固定顺序构建查询字符串之前,这很方便。

用 usort 和太空船运算符自定义顺序

usort($array, $callback) 让你决定顺序。回调函数接收两个元素:如果第一个应该排在前面,就返回负数;如果第二个应该排在前面,就返回正数;如果两者相等,就返回 0。太空船运算符 <=> 返回的正是这样的值。

banana 和 cherry 长度相同,所以回调对它们返回 0,它们保持原来的顺序。从 PHP 8.0 开始,PHP 的排序是稳定的:相等的元素保持之前的顺序。

按某个值给多维数组排序

要按某个字段给一组行排序,就在 usort 中比较这个字段。要按两个字段排序,就比较数组:<=> 会逐个元素比较,所以只有第一个字段相等时,第二个字段才起作用。

第二个比较把 $b["age"] 放在左边、$a["age"] 放在右边,这样只反转了年龄的顺序。array_multisort(array_column($people, 'city'), SORT_ASC, array_column($people, 'age'), SORT_DESC, $people) 不用回调也能得到相同的顺序:它按提取出来的列排序,并相应地重新排列 $people。

自然排序和排序标志

默认情况下,PHP 把数字当作数字比较,把字符串当作字符串比较。带数字的文件名排出来的顺序会出人意料:img10 排在 img2 前面,所有大写开头的名字都排在小写开头的名字前面。排序标志可以改变值的比较方式。

SORT_NATURAL 把连续的数字当作数字来读,SORT_FLAG_CASE 忽略大小写,SORT_STRING 即使对数字字符串也强制逐字符比较。natsort() 和 natcasesort() 是同样的思路,但会保留键。

常见错误:把 sort 的结果赋值给变量

所有排序函数都返回 true,并修改你传入的数组。把返回值赋给变量会丢掉数组:

如果需要一个排好序的副本,同时保留原数组,就先把数组复制到一个新变量中,再对副本排序,就像上面 asort 示例中对 $copy 所做的那样。

常见问题

为什么 sort() 返回的是 true,而不是排好序的数组?

PHP 的排序函数通过引用原地排序数组,并返回 true。把 sort($arr); 单独写成一行,之后再使用 $arr。写成 $arr = sort($arr); 会用 true 替换掉你的数组。

怎么按值给关联数组排序并保留键?

升序用 asort($arr),降序用 arsort($arr)。sort() 和 rsort() 也按值排序,但会丢掉键,从 0 开始重新编号。

PHP 中怎么按某个值给多维数组排序?

用 usort 配合太空船运算符比较这个字段:usort($rows, fn($a, $b) => $a['age'] <=> $b['age']);。交换 $a 和 $b 就是降序;要按两个字段排序,就比较数组,比如 [$a['city'], $a['age']] <=> [$b['city'], $b['age']]。

PHP 的排序是稳定的吗?

是的,从 PHP 8.0 开始,所有排序函数都是稳定的:比较结果相等的元素保持排序前的顺序。正因如此,先按一个字段排序再按另一个字段排序,才能得到预期的结果。

怎么按自然顺序给带数字的字符串排序?

使用 natsort($arr) 或 sort($arr, SORT_NATURAL),它们会把 img2 排在 img10 前面。加上 SORT_FLAG_CASE(SORT_NATURAL | SORT_FLAG_CASE)或使用 natcasesort 可以忽略大小写。

Coddy 编程语言插图

和 Coddy 一起学编程

开始