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

如何为排序后分数相同的列表元素分配相同的竞赛名次?

处理同分运动员的名次分配问题

这问题我之前做竞赛排名系统时也碰到过,直接用递增的名次肯定不行,得把连续同分的选手归为一组来处理~

核心思路

既然你的TreeSet已经按分数升序排好序了,我们可以先把集合转成List(方便按索引分组),然后通过分组遍历的方式:

  • 找到连续同分的运动员组
  • 计算每组的起始和结束名次,生成对应的名次标识(比如单人是"1",两人同分是"1-2")
  • 给组内所有运动员统一设置这个名次标识

代码实现

假设你的Athlete类有getScore()和setRelativePlace(String)方法,具体代码如下:

// 先把TreeSet转成ArrayList,保留排序后的顺序
List<Athlete> athleteList = new ArrayList<>(allAthletes);
int totalAthletes = athleteList.size();
int currentIndex = 0;

while (currentIndex < totalAthletes) {
    Athlete currentAthlete = athleteList.get(currentIndex);
    int currentScore = currentAthlete.getScore();
    
    // 找到当前分数的最后一位选手的索引
    int groupEndIndex = currentIndex;
    while (groupEndIndex < totalAthletes 
           && athleteList.get(groupEndIndex).getScore() == currentScore) {
        groupEndIndex++;
    }
    
    // 生成名次字符串
    String placeLabel;
    int groupSize = groupEndIndex - currentIndex;
    if (groupSize == 1) {
        // 单人组,直接用数字
        placeLabel = String.valueOf(currentIndex + 1);
    } else {
        // 多人同分,格式为"起始名次-结束名次"
        placeLabel = (currentIndex + 1) + "-" + groupEndIndex;
    }
    
    // 给当前组的所有选手设置名次
    for (int i = currentIndex; i < groupEndIndex; i++) {
        athleteList.get(i).setRelativePlace(placeLabel);
    }
    
    // 跳转到下一组的起始位置
    currentIndex = groupEndIndex;
}

注意事项

  1. 分数精度问题:如果你的分数是浮点数(比如double或float),不要直接用==判断相等,建议用精度阈值比较:
    Math.abs(athleteList.get(groupEndIndex).getScore() - currentScore) < 1e-9
    
  2. 排序方向:如果你的竞赛是高分者名次靠前,记得调整TreeSet的比较器,改成按分数降序排序,代码的分组逻辑不需要改动。
  3. 名次逻辑验证:比如3个选手分数相同,他们的名次会是"1-3",下一个不同分数的选手名次会从4开始,这符合竞赛排名的常规规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:19:00