如何合并数组中除指定键外其余相同的字典并聚合指定键值?
嘿,这个需求挺常见的,你当前的实现确实能达成目标,但可以用基于字典分组的方式大幅简化代码,同时提升性能!
优化后的实现方案
简洁高效版代码
from collections import defaultdict def merge_items_on_field(items, field): # 用defaultdict创建分组容器,键是除目标字段外的唯一标识,值是聚合后的字段集合 group_container = defaultdict(set) for item in items: # 生成分组键:将除field外的键值对转为排序后的元组(避免字典键顺序影响分组) group_key = tuple(sorted((k, v) for k, v in item.items() if k != field)) # 把当前项的field值合并到对应分组中 group_container[group_key].update(item[field]) # 将分组结果转换回目标字典数组格式 merged_items = [] for key, aggregated_field in group_container.items(): # 先把元组键转回基础字典 base_item = dict(key) # 添加聚合后的目标字段 base_item[field] = aggregated_field merged_items.append(base_item) return merged_items # 测试示例 items = [ {'FirstName': 'David', 'LastName': 'Smith', 'Language': set(['en'])}, {'FirstName': 'David', 'LastName': 'Smith', 'Language': set(['fr'])}, {'FirstName': 'Bob', 'LastName': 'Jones', 'Language': set(['en'])} ] print(merge_items_on_field(items, 'Language')) # 输出:[{'FirstName': 'David', 'LastName': 'Smith', 'Language': {'en', 'fr'}}, {'FirstName': 'Bob', 'LastName': 'Jones', 'Language': {'en'}}]
为什么这个方案更优?
- 代码更简洁:去掉了原实现中繁琐的
deepcopy、try-except和列表查找逻辑,核心逻辑一目了然,维护成本更低 - 性能提升明显:原方案的
index查找和多次deepcopy会带来O(n²)的时间复杂度,而分组方案是线性时间O(n),数据量越大,性能差距越显著 - 鲁棒性更强:通过
sorted处理键值对元组,避免了因字典键顺序不同导致的分组错误(比如原字典键顺序变化时,原方法可能误判为不同项,这个方案不会)
拓展:不用defaultdict的实现(Python 3.9+)
如果不想引入collections模块,也可以用普通字典+字典合并运算符实现:
def merge_items_on_field(items, field): group_container = {} for item in items: group_key = tuple(sorted((k, v) for k, v in item.items() if k != field)) if group_key not in group_container: group_container[group_key] = set() group_container[group_key].update(item[field]) # 用字典合并运算符快速生成结果 merged_items = [dict(group_key) | {field: vals} for group_key, vals in group_container.items()] return merged_items
注意事项
如果你的字典值包含不可哈希类型(比如列表),上面的分组键生成方式会报错。这种情况下,可以把不可哈希的值转为可哈希类型(比如列表转元组),或者根据实际业务逻辑调整分组键的生成规则。
内容的提问来源于stack exchange,提问作者David542
相关产品推荐
相关产品推荐

