You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP计算数组元素dense_rank与gapped_rank的代码问题排查

问题根因

现有代码的两类排名逻辑存在计数规则和变量使用错误:

  1. 间隔排名(gapped rank,即标准竞争排名:同值同名次,后续名次跳过已占用位次,例如两个并列第1后下一名次为第3)的逻辑未基于遍历实际位置赋值,初始值设置错误,也没有统计同值元素的占位数量。
  2. 密集排名(dense rank:同值同名次,后续名次紧接上一名次,例如两个并列第1后下一名次为第2)的逻辑在同值判断分支中多写了++$dense_rank自增逻辑,导致每遇到一个同值元素排名就上涨,只有碰到新数值时才会临时回归正确值,和你观察到的错误规律完全吻合。
修复后可运行代码
$members = [
    ['num' => 2, 'rank' => 0, 'dense_rank' => 0],
    ['num' => 2, 'rank' => 0, 'dense_rank' => 0],
    ['num' => 3, 'rank' => 0, 'dense_rank' => 0],
    ['num' => 3, 'rank' => 0, 'dense_rank' => 0],
    ['num' => 3, 'rank' => 0, 'dense_rank' => 0],
    ['num' => 3, 'rank' => 0, 'dense_rank' => 0],
    ['num' => 3, 'rank' => 0, 'dense_rank' => 0],
    ['num' => 5, 'rank' => 0, 'dense_rank' => 0],
    ['num' => 9, 'rank' => 0, 'dense_rank' => 0],
    ['num' => 9, 'rank' => 0, 'dense_rank' => 0],
    ['num' => 9, 'rank' => 0, 'dense_rank' => 0]    
];

// 排名计算前置要求:数组必须按num字段升序排序,若原始数组未排序请放开下方排序代码
/*
usort($members, function($a, $b){
    return $a['num'] <=> $b['num'];
});
*/

$gappedRank = 0;
$prevGappedNum = null;
$denseRank = 0;
$prevDenseNum = null;
$currentPos = 0;

foreach($members as &$item){
    $currentPos++;
    // 计算间隔排名
    if($item['num'] !== $prevGappedNum){
        $gappedRank = $currentPos;
        $prevGappedNum = $item['num'];
    }
    $item['rank'] = $gappedRank;

    // 计算密集排名
    if($item['num'] !== $prevDenseNum){
        $denseRank++;
        $prevDenseNum = $item['num'];
    }
    $item['dense_rank'] = $denseRank;

    echo $item['num'].' - '.$item['rank'].' - '.$item['dense_rank'].'<br>';
}
unset($item); // 解除引用避免后续数组操作出现值污染
正确输出结果

代码运行后排名完全符合规则:

num(数值)gapped rank(间隔排名)dense rank(密集排名)
211
211
332
332
332
332
332
583
994
994
994
性能说明

该实现为单次遍历O(n)时间复杂度,单组处理10万级数据无性能压力,完全适配你提到的每周批量处理动态组合的场景,不需要依赖数据库建表计算。

内容的提问来源于stack exchange,提问作者GregW

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 15:06:23