sort() 不保证重复元素的原始顺序,这是正常设计行为;需去重保序应使用 array_unique(),需稳定排序则需 usort() 等替代方案。

PHP 8.3 中用 sort() 或其他内置排序函数处理含重复元素的数组时,顺序“变了”,其实不是 bug,而是设计行为——sort() 会重排整个数组,原始出现顺序必然丢失。它只保证值升序(或按指定规则),不承诺保留相同值之间的先后关系。
重复元素在 sort() 后位置变动是正常现象
PHP 的 sort() 默认使用快速排序变体,对相等元素不做稳定性保证(尽管 PHP 8.0+ 在值完全相同时尽量保持原序,但这属于实现细节,不可依赖)。例如:
原数组:['c', 'a', 'b', 'a', 'c']
排序后可能为:['a', 'a', 'b', 'c', 'c'] —— 两个 'a' 谁前谁后、两个 'c' 的相对位置,都不受控。
这不是错误,是排序函数的固有特性:它面向「值有序」,而非「去重保序」或「稳定排序」。
需要保持首次出现顺序?别用 sort() 去重
如果你的真实目标是「去掉重复项,同时让每个唯一值按第一次出现的位置排列」,那根本不需要排序——这属于去重(deduplication)问题,不是排序问题。
-
array_unique($arr)就是为此设计:它删掉后续重复项,严格保留每个值首次出现的顺序和位置 - 若需连续数字键,再套一层
array_values()即可:$clean = array_values(array_unique($arr)); - 该方案时间复杂度 O(n),无排序开销,逻辑清晰,且 PHP 8.3 完全兼容
真要稳定排序重复元素?得换方法
如果业务确实要求「所有元素排序,且相等元素必须保持原始相对顺序」(即稳定排序),PHP 内置 sort() 不保证这一点。可行替代方案:
-
用
usort()+ 带索引的比较:把原数组带上键(如array_map(null, array_keys($arr), $arr)),在比较函数中,值相等时比原始键大小 - 小数据量可手动实现插入排序或归并排序:它们天然稳定,但一般没必要,除非有特殊约束
- 避免混淆目标:确认你是否真的需要“排序后的稳定”,还是误把“去重保序”当成了“排序保序”
不复杂但容易忽略:sort() 和 array_unique() 解决的是两类不同问题。选错工具,就会觉得“顺序变了”——其实是用错了地方。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











