Python 如何从含重复键的列表生成保留所有值的分组字典?
重复键值对分组聚合的字典实现
给定两个一一对应的平行列表:
keys = ['a', 'b', 'c', 'c'] values = [1, 2, 3, 4]
日常常用的字典构造写法dictionary = dict(zip(keys, values)),会利用Python字典键唯一的特性,自动覆盖重复键的旧值,最终运行结果为{'a': 1, 'b': 2, 'c': 4},直接丢失了键为c的第一个对应值3。
我们实际需要的输出效果为{'a': 1, 'b': 2, 'c': [3,4]}——即对相同键对应的所有值做分组存储,不丢弃任何原始配对数据。这类需求完全可以通过遍历配对、按需聚合的方式实现,常用的实现方案有以下两种:
方案1:无依赖基础遍历实现
逐一遍历zip打包的键值对,针对每个键的出现状态做判断:
- 键首次出现时,直接保存对应的原始值
- 键已存在时,先检查当前存储值是否为列表,非列表则先将原有值转为列表,再追加新值
result = {} for k, v in zip(keys, values): if k not in result: result[k] = v else: # 单值转列表,方便后续追加新值 if not isinstance(result[k], list): result[k] = [result[k]] result[k].append(v) print(result) # 输出: {'a': 1, 'b': 2, 'c': [3, 4]}
方案2:基于collections模块的简化实现
借助内置的defaultdict省去手动判断键是否存在的重复逻辑,最后再对聚合结果做格式转换,匹配“单值存原值、多值存列表”的要求:
from collections import defaultdict # 先按列表收集每个键对应的所有值 temp_result = defaultdict(list) for k, v in zip(keys, values): temp_result[k].append(v) # 格式转换:仅出现一次的键直接取原始值,重复出现的保留值列表 result = { k: val[0] if len(val) == 1 else val for k, val in temp_result.items() } print(result) # 输出: {'a': 1, 'b': 2, 'c': [3, 4]}
如果业务场景允许所有值统一以列表形式存储(比如后续需要批量遍历所有值的场景),可以直接省去结果转换的步骤,代码会更简洁。
实现注意事项
- 常规
dict(zip(...))的覆盖逻辑是Python字典的核心特性,重复键只会保留最后一次出现的对应值,这就是初始示例中丢失数据的根本原因。 - 聚合过程中一定要做好值的类型判断,避免把仅出现一次的键值误转成单元素列表,导致后续业务处理出现类型不兼容的问题。
内容的提问来源于stack exchange,提问作者yusuf imran
相关产品推荐
相关产品推荐

