如何查找值可包含列表的多个字典间的公共项
提取含嵌套字典列表的多字典公共项解决方案
问题背景
需要从多个字典组成的列表中提取公共键值对,规则如下:
- 字典键顺序不影响判定,内容一致即为公共项;
- 若值为字典组成的列表,列表元素顺序无关,但元素必须完全匹配(字典内部键顺序也不影响);
- 原代码仅支持非列表值,遇到列表时会抛出
TypeError: unhashable type: 'list',因为集合操作要求元素可哈希,而列表不可哈希。
解决方案
核心思路是递归处理嵌套结构,先判断值的类型,对字典、列表分别做顺序无关的相等验证,再遍历所有字典的公共键,逐个验证对应值是否满足要求。
1. 递归相等验证函数
该函数处理不同类型的值,实现顺序无关的相等判定:
def are_values_equal(val1, val2): # 字典类型:先比较键集合,再递归比较每个键对应的值 if isinstance(val1, dict) and isinstance(val2, dict): if val1.keys() != val2.keys(): return False for key in val1: if not are_values_equal(val1[key], val2[key]): return False return True # 列表类型:先比较长度,再把元素转成可哈希结构后用集合比较(忽略顺序) elif isinstance(val1, list) and isinstance(val2, list): if len(val1) != len(val2): return False # 把嵌套结构转成可哈希的元组 def to_hashable(item): if isinstance(item, dict): return tuple(sorted(item.items())) # 字典转排序后的键值对元组 elif isinstance(item, list): return tuple(to_hashable(i) for i in item) # 递归处理列表中的列表 else: return item return set(to_hashable(item) for item in val1) == set(to_hashable(item) for item in val2) # 其他基础类型直接比较 else: return val1 == val2
2. 主函数提取公共项
先找出所有字典的公共键,再逐个验证键对应的值是否在所有字典中满足顺序无关的相等:
def extract_common_values(list_of_dicts): if not list_of_dicts: return {} # 第一步:找出所有字典的公共键 common_keys = set(list_of_dicts[0].keys()) for d in list_of_dicts[1:]: common_keys.intersection_update(d.keys()) # 第二步:验证每个公共键对应的值是否在所有字典中匹配 common_dict = {} base_dict = list_of_dicts[0] for key in common_keys: base_val = base_dict[key] # 检查所有其他字典的该键值是否与基准值匹配 match_all = True for d in list_of_dicts[1:]: if not are_values_equal(base_val, d[key]): match_all = False break if match_all: common_dict[key] = base_val return common_dict
测试验证
示例1:字典列表元素内部键顺序不同
d1 = {'a': 1, 'b': [{'c':1,'d':2},{'e':3,'f':4}]} d2 = {'a': 1, 'b': [{'c':1,'d':2},{'f':4,'e':3}], 'g':4} print(extract_common_values([d1, d2])) # 输出:{'a': 1, 'b': [{'c': 1, 'd': 2}, {'e': 3, 'f': 4}]}
示例2:字典列表元素顺序不同
d1 = {'a': 1, 'b': [{'c':1,'d':2},{'e':3,'f':4}]} d2 = {'a': 1, 'b': [{'f':4,'e':3},{'c':1,'d':2}], 'g':4} print(extract_common_values([d1, d2])) # 输出:{'a': 1, 'b': [{'c': 1, 'd': 2}, {'e': 3, 'f': 4}]}
示例3:字典列表元素不匹配
d1 = {'a': 1, 'b': [{'c':1,'d':2},{'e':3,'f':{'h':5}}]} d2 = {'a': 1, 'b': [{'c':1,'d':2},{'f':4,'e':3}], 'g':4} print(extract_common_values([d1, d2])) # 输出:{'a': 1}
原代码问题说明
原代码使用dict.items()的集合交集操作,要求键值对中的值必须是可哈希类型(如字符串、数字、元组),但列表是不可哈希类型,因此触发TypeError。本方案通过递归处理嵌套结构,避免了直接使用集合哈希操作,同时满足顺序无关的判定规则。
内容的提问来源于stack exchange,提问作者Kspr
相关产品推荐
相关产品推荐

