python:只查找几个dicts的公共键值对:dict intersection

时间:2012-03-28 11:53:12

标签: python

我在列表中有0个或更多个dicts:

>>> dicts = [dict(a=3, b=89, d=2), dict(a=3, b=89, c=99), dict(a=3, b=42, c=33)]

我想创建一个新的字典,其中只包含 all 上述字符串中的键,并且只有在值完全相同时才会显示:

>>> dict_intersection(*dicts)
{"a": 3}

我觉得应该有一种优雅的写作方式dict_intersection,但我自己只会提出不优雅和/或低效的解决方案。建议?

5 个答案:

答案 0 :(得分:18)

>>> dict(set.intersection(*(set(d.iteritems()) for d in dicts)))
{'a': 3}

注意:除了键之外,此解决方案还要求字典值可以清除。

答案 1 :(得分:4)

由于键/值对必须已经在第一个dict中,因此您可以遍历此dict的项目。

dict(pair for pair in dicts[0].items() 
     if all((pair in d.items() for d in dicts[1:])))

看起来不如interjay的答案那么优雅,但是没有可用值的限制。

编辑:将all表达式更改为生成器表达式以提高速度

答案 2 :(得分:3)

>>> dicts
[{'a': 3, 'b': 89, 'd': 2}, {'a': 3, 'c': 99, 'b': 89}, {'a': 3, 'c': 33, 'b': 42}]
>>> sets = (set(d.iteritems()) for d in dicts)
>>> dict_intersection = dict(set.intersection(*sets))
>>> dict_intersection
{'a': 3}

答案 3 :(得分:3)

这是怎么回事?

def intersect_two_dicts (d1, d2):
    return { k:v for k,v in d1.iteritems() if ((k in d2)and(d1[k]==d2[k])) }

def intersect_dicts (list_of_dicts):
    return reduce(intersect_two_dicts, list_of_dicts)

# Tests
dicts = [dict(a=3, b=89, d=2), dict(a=3, b=89, c=99), dict(a=3, b=42, c=33)]
print (intersect_two_dicts(dicts[0], dicts[1]))
print (intersect_dicts(dicts))

编辑(1):我不确定哪一个是最快的。 set.intersection解决方案当然最优雅(一个衬里!)但我有兴趣看一些基准测试。

编辑(2):奖励 - 获取任何字典条目,其(键:值)对是任何两个字典共有的:

{k:count for k,count in
 collections.Counter(itertools.chain(*[d.iteritems() for d in dicts])).iteritems()
 if count > 1}

答案 4 :(得分:1)

稍微有点吝啬的方法:获取每个字典的键列表,对每个列表进行排序,然后继续进行,就好像要合并它们一样(为每个列表保留一个索引,使每个列表的索引前进一个) 。每当所有索引指向同一个键时,检查值是否相等;无论哪种方式,推进所有指数。