按绝对出现次数排名对象:Python代码逻辑错误排查
欧洲足球式排名逻辑实现错误排查与修复
我有一个包含浮点数的字典列表,需要按照欧洲足球排名逻辑(相同值的对象获得相同排名,下一位次跳过已占用的数量)进行排名。但当前代码输出不符合预期:比如值为19.07的对象预期排名为4,实际却得到3。我的思路是提取唯一值并跟踪前序对象的出现次数来计算排名,请问代码哪里出错了?
预期输出
{'value': {'total': 19.93}, 'rank': 1} {'value': {'total': 19.93}, 'rank': 1} {'value': {'total': 19.93}, 'rank': 1} {'value': {'total': 19.07}, 'rank': 4} {'value': {'total': 18.24}, 'rank': 5} {'value': {'total': 18.24}, 'rank': 5} {'value': {'total': 18.24}, 'rank': 5} {'value': {'total': 17.15}, 'rank': 8} {'value': {'total': 16.8}, 'rank': 9} {'value': {'total': 16.8}, 'rank': 9} {'value': {'total': 16.8}, 'rank': 9}
实际输出
{'value': {'total': 19.93}, 'rank': 1} {'value': {'total': 19.93}, 'rank': 1} {'value': {'total': 19.93}, 'rank': 1} {'value': {'total': 18.24}, 'rank': 3} {'value': {'total': 18.24}, 'rank': 3} {'value': {'total': 18.24}, 'rank': 3} {'value': {'total': 19.07}, 'rank': 4} {'value': {'total': 17.15}, 'rank': 5} {'value': {'total': 16.8}, 'rank': 6} {'value': {'total': 16.8}, 'rank': 6} {'value': {'total': 16.8}, 'rank': 6}
原代码
import random def rank_lista(ordered_list): vals = [] # add all values into a list for list_item in ordered_list: try: vals.append(list_item['value']['total']) except Exception as e: print (e) unique_values = sorted(list(set(vals))) sorted_list = [] for ooo in reversed(list(unique_values)): sorted_list.append(ooo) unique_values = [] unique_values = sorted_list print ('sorted unique values:', unique_values) for ordered_list_item in ordered_list: try: val = ordered_list_item['value']['total'] if unique_values.index(val) == 0: ordered_list_item['rank'] = unique_values.index(val)+1 elif unique_values.index(val) == 1: previous_value_index = 0 previous_value_count = vals.count(unique_values[previous_value_index]) ordered_list_item['rank'] = 1 + previous_value_count else: previous_value_index = unique_values.index(val)-1 previous_value_count = vals.count(unique_values[previous_value_index]) ordered_list_item['rank'] = (previous_value_index + 1) + previous_value_count except Exception as e: print (e,2) return ordered_list def create_random_list(): unique_rounded_floats = list(set(round(random.uniform(1, 20), 2) for _ in range(9))) floats_with_duplicates = [item for sublist in [[float_] * 3 for float_ in unique_rounded_floats] for item in sublist] other_floats = [round(random.uniform(1, 20), 2) for _ in range(11)] result_array = floats_with_duplicates + other_floats arr = [] for r in result_array: obj = {} obj['value'] = {'total':r} arr.append(obj) return arr random_list = create_random_list() print (random_list) result_list = sorted(rank_lista(random_list), key=lambda d: float(d['rank']), reverse = False) for res in result_list: print (res)
错误分析
- 排名计算逻辑错误:原代码仅累加了当前值的前一个唯一值的出现次数,而不是累加当前值之前所有更高数值的总出现次数。比如计算19.07的排名时,应该是前面所有更高值(19.93)的总数量(3)加1,得到4;但原代码在处理非前两个唯一值时,用
(previous_value_index + 1) + previous_value_count的计算方式完全错误,导致排名计算偏差。 - 结果排序逻辑错误:原代码最后按rank升序排序,但没有先按数值降序排序,导致数值高的对象可能排在后面(比如19.07出现在18.24之后),不符合预期的数值从高到低的展示顺序。
修正后的代码
import random def rank_lista(ordered_list): # 先按数值降序排序列表,保证输出顺序符合预期 sorted_by_value = sorted(ordered_list, key=lambda x: x['value']['total'], reverse=True) vals = [item['value']['total'] for item in sorted_by_value] # 获取降序排列的唯一值 unique_values = sorted(list(set(vals)), reverse=True) # 预计算每个唯一值对应的累计前置数量(前面所有更高值的总出现次数) rank_map = {} cumulative_count = 0 for val in unique_values: rank_map[val] = cumulative_count + 1 cumulative_count += vals.count(val) # 为每个对象分配排名 for item in sorted_by_value: item['rank'] = rank_map[item['value']['total']] return sorted_by_value def create_random_list(): unique_rounded_floats = list(set(round(random.uniform(1, 20), 2) for _ in range(9))) floats_with_duplicates = [item for sublist in [[float_] * 3 for float_ in unique_rounded_floats] for item in sublist] other_floats = [round(random.uniform(1, 20), 2) for _ in range(11)] result_array = floats_with_duplicates + other_floats arr = [] for r in result_array: obj = {} obj['value'] = {'total':r} arr.append(obj) return arr random_list = create_random_list() print("原始列表:", random_list) result_list = rank_lista(random_list) print("\n排名结果:") for res in result_list: print(res)
修正说明
- 先对原始列表按数值降序排序,确保输出时数值从高到低排列,符合预期展示逻辑。
- 预计算
rank_map字典,存储每个唯一值对应的排名:遍历降序的唯一值,累计前面所有值的出现次数,当前值的排名就是累计数+1。 - 直接通过
rank_map给每个对象分配排名,逻辑清晰且高效,避免了原代码中多次调用index()和count()的低效操作。
内容的提问来源于stack exchange,提问作者rihekopo
相关产品推荐
相关产品推荐

