You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Python 3.x实现无跳号密集排序(Dense Rank)技术问询

解决Python密集排序(Dense Rank)跳号问题

我来帮你搞定这个密集排序的问题!你当前代码里用sorted_scores.index(x)的问题在于,它会返回每个分数第一次出现的索引,所以重复分数后面的元素会直接跳过中间的位置,导致排名跳号。比如两个71分的元素,第一个在索引5,第二个也取5,排名都是6,但下一个67分的第一个位置是索引7,所以排名变成8,就跳过了7,这就是你看到的跳号情况。

下面给你两种简洁的实现方式,都能得到你想要的无跳号排名:

方法一:遍历跟踪法(直观易懂)

这种方法直接遍历排序后的列表,维护当前排名和上一个分数,遇到相同分数就保持排名,不同分数就递增排名:

rank_list = [{'Id': 236966, 'score': 91.0}, {'Id': 237241, 'score': 82.0}, {'Id': 237077, 'score': 79.0}, {'Id': 237084, 'score': 78.0}, {'Id': 237080, 'score': 72.0}, {'Id': 237236, 'score': 71.0}, {'Id': 236979, 'score': 71.0}, {'Id': 236909, 'score': 67.0}, {'Id': 237174, 'score': 67.0}, {'Id': 237035, 'score': 66.0}]

# 先按分数降序排序(你原来的排序逻辑是对的)
rank_list.sort(key=lambda e: e['score'], reverse=True)

current_rank = 1
previous_score = rank_list[0]['score']
rank_list[0]['rank'] = current_rank

for obj in rank_list[1:]:
    if obj['score'] == previous_score:
        # 分数相同,排名不变
        obj['rank'] = current_rank
    else:
        # 分数不同,排名递增
        current_rank += 1
        obj['rank'] = current_rank
        previous_score = obj['score']

# 验证输出
for item in rank_list:
    print(item)

运行后每个元素的rank就是[1, 2, 3, 4, 5, 6, 6, 7, 7, 8],完全符合你的期望。

方法二:字典映射法(适合大数据量)

如果你的列表很大,遍历一次生成分数到排名的映射,再批量赋值会更高效:

rank_list = [{'Id': 236966, 'score': 91.0}, {'Id': 237241, 'score': 82.0}, {'Id': 237077, 'score': 79.0}, {'Id': 237084, 'score': 78.0}, {'Id': 237080, 'score': 72.0}, {'Id': 237236, 'score': 71.0}, {'Id': 236979, 'score': 71.0}, {'Id': 236909, 'score': 67.0}, {'Id': 237174, 'score': 67.0}, {'Id': 237035, 'score': 66.0}]

rank_list.sort(key=lambda e: e['score'], reverse=True)

# 生成唯一分数的排序列表,然后创建分数到密集排名的映射
unique_scores = sorted({obj['score'] for obj in rank_list}, reverse=True)
score_rank_map = {score: idx+1 for idx, score in enumerate(unique_scores)}

# 给每个元素赋值rank
for obj in rank_list:
    obj['rank'] = score_rank_map[obj['score']]

# 验证输出
for item in rank_list:
    print(item)

这个方法先提取所有唯一的分数并降序排序,然后给每个唯一分数分配连续的排名,最后直接通过字典映射给每个元素赋值,逻辑也很清晰,而且大数据量下比遍历判断的方式更快。

这两种方法都能解决你当前的跳号问题,你可以根据自己的需求选择~

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

火山引擎 最新活动