我在列表中有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
,但我自己只会提出不优雅和/或低效的解决方案。建议?
答案 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)
稍微有点吝啬的方法:获取每个字典的键列表,对每个列表进行排序,然后继续进行,就好像要合并它们一样(为每个列表保留一个索引,使每个列表的索引前进一个) 。每当所有索引指向同一个键时,检查值是否相等;无论哪种方式,推进所有指数。