一、rsort()的定位
PHP的排序函数按两个维度分类:按值还是按键,升序还是降序。rsort()属于"按值降序"这一类。
它的名字可以拆开理解:r表示reverse(降序),sort表示按值排序。和它对应的是sort()(按值升序)。按键排序的那一组则是ksort()和krsort()。
用之前要明确一点:rsort()会破坏键值对应关系。排序后数字键重新从0开始编号,字符串键直接丢失,只保留值。这个特性决定了它适合"列表类"数据,不适合"映射类"数据。
二、函数原型与参数
rsort(array &$array, int $sort_flags = SORT_REGULAR): bool
| 参数 | 说明 | 是否必需 |
|---|---|---|
| array | 待排序的数组,以引用传入 | 必需 |
| sort_flags | 排序标志,指定比较方式 | 可选 |
返回值:成功返回true,失败返回false。
参数是引用传递,函数直接修改原数组,不返回排序后的数组。这一点和array_reverse()不同,后者返回新数组。写代码时如果$result=rsort($arr),$result拿到的是true/false,不是数组。这是新手常犯的错误。
三、sort_flags排序标志
| 标志 | 含义 |
|---|---|
| SORT_REGULAR | 默认,按常规方式比较,不转换类型 |
| SORT_NUMERIC | 按数值比较 |
| SORT_STRING | 按字符串比较 |
| SORT_LOCALE_STRING | 按本地化字符串比较 |
| SORT_NATURAL | 自然排序,如"img10"排在"img2"之后 |
| SORT_FLAG_CASE | 可与SORT_STRING组合,忽略大小写 |
默认的SORT_REGULAR会按PHP的类型比较规则来,数字和数字比大小,字符串和字符串比字典序。混合类型时结果可能不符合直觉,这时候需要显式指定标志。
四、基本用法
数字数组降序:
<?php
$numbers = array(400, 600, 100, 220, 110);
rsort($numbers);
print_r($numbers);
输出:
Array
(
[0] => 600
[1] => 400
[2] => 220
[3] => 110
[4] => 100
)
键名被重新编号为0到4,值和顺序都符合预期。
字符串数组降序:
<?php
$cars = array("hexa", "nexon", "audi");
rsort($cars, SORT_REGULAR);
print_r($cars);
输出:
Array
(
[0] => nexon
[1] => hexa
[2] => audi
)
按字典序从大到小,n排在h前面,h排在a前面。
五、关联数组的键会丢失
这是rsort()使用中最需要留意的地方:
<?php
$fruit = array("d" => "mango", "a" => "orange", "b" => "banana");
rsort($fruit);
print_r($fruit);
输出:
Array
(
[0] => orange
[1] => mango
[2] => banana
)
原本的键d、a、b全部消失,值按降序重新排列,键变成0、1、2。如果业务上需要保留"哪个键对应哪个值",rsort()会把这个信息破坏掉。
需要保留键值对应关系时,应该用arsort()(按值降序,保留键)或krsort()(按键降序,保留键)。这三个函数的区别如下:
| 函数 | 排序依据 | 方向 | 键名 |
|---|---|---|---|
| sort() | 值 | 升序 | 重新编号 |
| rsort() | 值 | 降序 | 重新编号 |
| asort() | 值 | 升序 | 保留 |
| arsort() | 值 | 降序 | 保留 |
| ksort() | 键 | 升序 | 保留 |
| krsort() | 键 | 降序 | 保留 |
个人经验:做过一个商品销量排行榜,数据是['商品ID'=>销量]的关联数组。一开始用rsort()排序,排完销量顺序对了,但商品ID全没了,前端拿不到该展示哪个商品。换成arsort()后,销量降序排列,商品ID依然挂在对应的销量上。需要"排序后还知道这条数据是谁"的场景,一律用arsort(),不要用rsort()。
六、混合类型数组的排序
数组里同时有数字和数字字符串时,SORT_REGULAR的比较结果可能和预期不同:
<?php
$mixed = array("10", 9, "100", 20);
rsort($mixed, SORT_REGULAR);
print_r($mixed);
SORT_REGULAR下,PHP会把数字字符串按数值比较,结果通常是100、20、10、9的降序。但如果数组里混入了非数字字符串,比较规则会变,结果可能不稳定。处理混合类型数据时,显式指定SORT_NUMERIC或SORT_STRING,比依赖默认行为更可靠。
另一个常见坑是版本差异。PHP8之前和之后,字符串与数字的比较规则有过调整,同一段代码在不同版本下排序结果可能不同。项目里如果对排序顺序有严格要求,指定明确的sort_flags是稳妥的做法。
七、项目实例
实例一:成绩降序排名
<?php
$scores = array(88, 95, 72, 91, 85);
rsort($scores);
print_r($scores);
输出:
Array
(
[0] => 95
[1] => 91
[2] => 88
[3] => 85
[4] => 72
)
纯数值列表排序,不需要保留原下标,rsort()直接可用。
实例二:保留商品ID的销量排行
<?php
$sales = array(
'p101' => 320,
'p102' => 580,
'p103' => 210,
);
arsort($sales);
print_r($sales);
输出:
Array
(
[p102] => 580
[p101] => 320
[p103] => 210
)
这里用的是arsort()而不是rsort()。原因就是商品ID必须保留,否则排序结果无法对应到具体商品。这是本节最值得记住的一个取舍点。
实例三:文件名自然降序
<?php
$files = array("img2.jpg", "img10.jpg", "img1.jpg");
rsort($files, SORT_NATURAL);
print_r($files);
输出:
Array
(
[0] => img10.jpg
[1] => img2.jpg
[2] => img1.jpg
)
用SORT_NATURAL时,img10会排在img2前面(因为10大于2)。如果不用这个标志,按字符串比较,img2会排在img10前面,因为字符"2"大于"1"。处理带数字的文件名、版本号时,SORT_NATURAL更符合人的阅读习惯。
八、踩坑记录
坑一:把rsort()的返回值当数组用。rsort()返回bool,排序结果在原数组里。$sorted=rsort($arr)这种写法拿不到数组。
坑二:对关联数组用rsort()丢键。需要保留键值对应关系时,用arsort()而不是rsort()。
坑三:混合类型不指定sort_flags。默认的SORT_REGULAR在混合类型下比较规则复杂,结果不稳定。明确数据类型后指定SORT_NUMERIC或SORT_STRING。
坑四:以为排序是稳定的。PHP8.0之前,排序不保证相等元素的相对顺序。PHP8.0起排序变为稳定排序,但依赖这个特性前应确认运行环境的版本。
坑五:数值字符串比较。表单提交的数值是字符串类型,用SORT_REGULAR可能按字符串比较,出现"100"排在"20"前面的情况。数值排序应显式传SORT_NUMERIC。
坑六:rsort()和array_reverse()混用。想让有序数组倒过来,用array_reverse();想对无序数组降序排列,用rsort()。前者是反转顺序,后者是按值排序,语义不同。
九、本节课程知识要点
-
rsort()按值降序排序,直接修改原数组,返回bool。
-
排序后数字键重新编号,字符串键丢失,这是它的固有行为。
-
需要保留键值对应关系时,用arsort(),不要用rsort()。
-
sort_flags控制比较方式,混合类型数据应显式指定。
-
带数字的文件名、版本号排序,用SORT_NATURAL更符合阅读习惯。
-
rsort()是排序,array_reverse()是反转顺序,两者用途不同。
十、常见问题
问:rsort()会返回排序后的数组吗?
不会。它返回true或false,排序结果直接写回传入的数组变量。
问:rsort()和arsort()有什么区别?
rsort()排序后键名重新编号,字符串键丢失;arsort()按值降序排序但保留原有的键值对应关系。
问:字符串数组排序能忽略大小写吗?
可以。传SORT_STRING|SORT_FLAG_CASE,这样大写和小写字母会被视为相同再排序。
问:排序后相等元素的顺序会变吗?
PHP8.0起排序是稳定的,相等元素保持原有相对顺序。更早的版本不保证这一点。
问:能不能只排序数组的一部分?
rsort()作用于整个数组。局部排序需要先array_slice()截取,排序后再拼回原数组。