字典排序练习:矮人数据处理任务的替代方案与代码优化咨询
矮人数据处理任务的替代实现与优化方案
一、更简洁的实现方式
直接用(姓名, 帽子颜色)元组作为字典的唯一键,天然解决“姓名+帽子颜色唯一”的规则;用collections.Counter快速统计每种帽子的矮人数量,整个逻辑更紧凑:
from collections import Counter def process_dwarfs(): dwarfs = {} while True: line = input().strip() if line == "Once upon a time": break # 一次拆分完成赋值,避免重复调用split name, hat, physics = line.split(" <:> ") physics = int(physics) # 元组作为键,直接处理力量值替换逻辑 key = (name, hat) if key not in dwarfs or physics > dwarfs[key]: dwarfs[key] = physics # 统计每种帽子对应的矮人总数 hat_dwarf_count = Counter(hat for name, hat in dwarfs.keys()) # 多条件排序:先按力量降序,再按同帽子矮人数量降序 sorted_dwarfs = sorted( dwarfs.items(), key=lambda item: (-item[1], -hat_dwarf_count[item[0][1]]) ) # 格式化输出 for (name, hat), physics in sorted_dwarfs: print(f"({hat}) {name} <-> {physics}") process_dwarfs()
二、原有代码的优化点
1. 减少重复的split调用
原代码中对同一行字符串调用了3次split(" <:> "),改成一次拆分后直接赋值,既提升效率又更简洁:
# 原写法 dwarf_name, dwarf_hat_color, dwarf_physics = dwarf_info.split(" <:> ")[0], dwarf_info.split(" <:> ")[1], int(dwarf_info.split(" <:> ")[2]) # 优化后 name, hat, physics = dwarf_info.split(" <:> ") physics = int(physics)
2. 简化嵌套字典的判断逻辑
用dict.setdefault()替代多层if-else,直接获取对应帽子的子字典,再处理姓名对应的力量值:
def collecting_data(): dwarfs_dict = {} while True: dwarf_info = input().strip() if dwarf_info == "Once upon a time": return dwarfs_dict name, hat, physics = dwarf_info.split(" <:> ") physics = int(physics) # 自动创建不存在的帽子字典,避免多层判断 hat_dict = dwarfs_dict.setdefault(hat, {}) # 直接判断并更新最大力量值 if name not in hat_dict or physics > hat_dict[name]: hat_dict[name] = physics
3. 排序逻辑简化
原代码先构建包含number字段的列表,其实可以在排序时动态获取帽子的矮人数量,避免提前存储:
def sorting_dwarfs(): dict_with_dwarfs = collecting_data() # 直接生成待排序的元组列表 dwarf_list = [] for hat, name_physics in dict_with_dwarfs.items(): count = len(name_physics) for name, physics in name_physics.items(): dwarf_list.append( (physics, count, hat, name) ) # 排序时对前两个值取负实现降序 for physics, count, hat, name in sorted(dwarf_list, key=lambda x: (-x[0], -x[1])): print(f"({hat}) {name} <-> {physics}")
三、sorted函数用法解析与"unhashable dict"错误解决
sorted核心用法
sorted(iterable, key=None, reverse=False)的核心是key参数:它接受一个函数,返回用于排序的依据值。默认按升序排列,要实现降序有两种方式:
- 对数值类型的依据值取负(比如
-physics),适合多条件排序时区分不同字段的排序方向; - 设置
reverse=True,适合单一条件的降序。
解决"unhashable dict"错误
这个错误的本质是:字典是可变类型,不可被哈希,当你尝试把字典作为字典的键、放进集合,或者在key函数中返回字典时,就会触发这个错误。
你最初尝试排序嵌套字典时出错,大概率是直接把嵌套的子字典(比如dwarfs_dict[hat])作为排序元素,或者用字典作为key的一部分。解决办法是:永远用可哈希类型(元组、字符串、数字等不可变类型)作为排序依据或字典键——比如我们前面用的(name, hat)元组,就是典型的可哈希唯一标识。
多条件排序示例
比如你的需求是“力量降序→同帽子数量降序”,对应的key函数要返回一个元组,元组内元素的优先级从左到右:
# 方式1:对需要降序的数值取负 key=lambda item: (-item[1], -hat_dwarf_count[item[0][1]]) # 方式2:结合reverse,但多条件时不如取负灵活 key=lambda item: (item[1], hat_dwarf_count[item[0][1]]), reverse=True
内容的提问来源于stack exchange,提问作者KNenov
相关产品推荐
相关产品推荐

