Python 3.4中如何保留字典重复键以完整生成嵌套字典并排序
解决Python字典重复键丢失条目问题
问题背景
我希望最后一个用于排序的for循环能展示字典names的所有条目,包括重复键(一对多映射)的条目。但在生成嵌套字典列表users时,有2个Tom和1个Bernie条目丢失,如何在Python 3.4中避免该问题?
原始代码
from operator import itemgetter names = { 'Bucky': 'Roberts', 'Tom': 'Roberts', 'Bernie' : 'Zunks', 'Jenna' : 'Hayes', 'Sally': 'Jones', 'Amanda':'Roberts', 'Tom':'Williams', 'Dean':'Hayes', 'Bernie':'Barbie', 'Tom':'Jones' } users = [] for k,v in names.items(): users.append({'fname':k,'lname':v}) print(users) for x in sorted(users, key=itemgetter('fname')): print(x)
问题原因
其实你踩了Python字典的一个基础特性:字典的键是绝对唯一的。当你在names里重复给同一个键赋值时,后面的值会直接覆盖掉前面的。比如Tom先后被赋值三次,最终字典里只会留下最后一次的Tom: Jones;Bernie两次赋值后也只剩Bernie: Barbie。所以遍历字典items()的时候,自然拿不到那些被覆盖的旧条目。
两种可行解决方案
方案1:用列表+元组存储原始数据
既然字典存不了重复键的条目,那我们直接用元组列表来保存所有原始键值对,这样就能完整保留每一条数据:
from operator import itemgetter # 把原来的字典改成元组列表,保留所有条目 names = [ ('Bucky', 'Roberts'), ('Tom', 'Roberts'), ('Bernie', 'Zunks'), ('Jenna', 'Hayes'), ('Sally', 'Jones'), ('Amanda', 'Roberts'), ('Tom', 'Williams'), ('Dean', 'Hayes'), ('Bernie', 'Barbie'), ('Tom', 'Jones') ] users = [] for k, v in names: users.append({'fname': k, 'lname': v}) print(users) # 排序后输出所有条目 for x in sorted(users, key=itemgetter('fname')): print(x)
运行这段代码,你就能看到所有3个Tom和2个Bernie的条目都被保留并排序输出了。
方案2:用defaultdict实现多值映射
如果后续还需要按键来管理多个值,可以用collections模块里的defaultdict来构建一个多值字典,把同一个键对应的所有值都存到列表里,之后再展开成你需要的users列表:
from operator import itemgetter from collections import defaultdict # 先把原始条目用列表+元组保存(避免字典覆盖) raw_entries = [ ('Bucky', 'Roberts'), ('Tom', 'Roberts'), ('Bernie', 'Zunks'), ('Jenna', 'Hayes'), ('Sally', 'Jones'), ('Amanda', 'Roberts'), ('Tom', 'Williams'), ('Dean', 'Hayes'), ('Bernie', 'Barbie'), ('Tom', 'Jones') ] # 用defaultdict存储每个键对应的多个值 multi_value_dict = defaultdict(list) for fname, lname in raw_entries: multi_value_dict[fname].append(lname) # 展开成users列表 users = [] for fname, lnames in multi_value_dict.items(): for lname in lnames: users.append({'fname': fname, 'lname': lname}) # 排序输出 for x in sorted(users, key=itemgetter('fname')): print(x)
这个方案适合需要先对同键的值做批量处理,再展开的场景。
小提示
虽然Python 3.7及以后的字典会保留插入顺序,但键的唯一性是所有Python版本字典的固有属性,所以只要用字典存重复键,就一定会出现覆盖丢失的问题。如果你的原始数据来自外部(比如文件、接口),一定要在读取阶段就用列表/元组保存,别直接转成字典。
内容的提问来源于stack exchange,提问作者Rex5
相关产品推荐
相关产品推荐

