如何对含重复值的数组排名并保留原数组顺序?
实现保留原顺序的重复值数组排名
首先明确需求:给包含重复值的数组生成排名,要求重复元素对应相同排名,且排名结果保留原数组的元素顺序,几个典型示例如下:
- 输入数组
(6,4,7,12,7)→ 预期排名(2,1,3,4,3) - 输入数组
(12,17,5,27,5)→ 预期排名(2,3,1,4,1) - 输入数组
(1,1,4,6)→ 预期排名(1,1,2,3)
你提供的代码存在的问题
这段代码无法正确实现需求,核心问题出在重复元素的处理上:
当你用sort()对原数组排序后,重复元素会保留各自的索引(比如输入[12,17,5,27,5]排序后是[5,5,12,17,27]),原数组中第二个5会匹配到排序数组里索引为1的位置,最终输出排名是1+1=2,但我们需要的是和第一个5相同的排名1。
简单说,这段代码会给重复元素分配不同的排名,不符合需求。
正确的实现方法
我们可以通过“建立值与排名的映射表”来解决这个问题,步骤如下:
- 对原数组去重后排序,得到一个无重复的有序数组
- 为这个有序数组创建“元素值→对应排名”的映射(排名从1开始)
- 遍历原数组,直接通过映射表获取每个元素的排名,既保留原顺序,又保证重复元素同排名
代码示例
$values = array(12,17,5,27,5); // 1. 去重并排序,得到无重复的有序数组 $uniqueSorted = array_unique($values); sort($uniqueSorted); // 2. 建立元素值到排名的映射(排名从1开始) // 用range生成从1到数组长度的排名序列,和有序数组组合成映射 $rankMap = array_combine($uniqueSorted, range(1, count($uniqueSorted))); // 3. 遍历原数组,获取每个元素的排名 $ranks = []; foreach ($values as $value) { $currentRank = $rankMap[$value]; $ranks[] = $currentRank; echo $value . ' has rank: ' . $currentRank . '<br>'; } // 输出最终排名数组,和预期一致 print_r($ranks); // 输出:Array ( [0] => 2 [1] => 3 [2] => 1 [3] => 4 [4] => 1 )
代码验证
拿示例数组(6,4,7,12,7)测试:
- 去重排序后得到
[4,6,7,12] - 映射表为
[4=>1, 6=>2,7=>3,12=>4] - 遍历原数组得到排名
[2,1,3,4,3],完全符合预期。
优势说明
这种方法比嵌套循环的效率更高(尤其是处理大数组时),而且逻辑清晰,能完美满足“重复元素同排名+保留原顺序”的需求。
内容的提问来源于stack exchange,提问作者Lord Null
相关产品推荐
相关产品推荐

