You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何查找值可包含列表的多个字典间的公共项

提取含嵌套字典列表的多字典公共项解决方案

问题背景

需要从多个字典组成的列表中提取公共键值对,规则如下:

  • 字典键顺序不影响判定,内容一致即为公共项;
  • 若值为字典组成的列表,列表元素顺序无关,但元素必须完全匹配(字典内部键顺序也不影响);
  • 原代码仅支持非列表值,遇到列表时会抛出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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 07:35:20