python:只查找几个dict的公共键值对:dict交集
我在列表中有0个或多个DICT:python:只查找几个dict的公共键值对:dict交集,python,Python,我在列表中有0个或多个DICT: >>> dicts = [dict(a=3, b=89, d=2), dict(a=3, b=89, c=99), dict(a=3, b=42, c=33)] 我想创建一个新的dict,该dict仅包含上述dict中所有的键,并且仅当值都相同时: >>> dict_intersection(*dicts) {"a": 3} 我觉得应该有一种优雅的方式来编写dict_intersection,但我自己只提出了不雅观和/或低
>>> dicts = [dict(a=3, b=89, d=2), dict(a=3, b=89, c=99), dict(a=3, b=42, c=33)]
我想创建一个新的dict,该dict仅包含上述dict中所有的键,并且仅当值都相同时:
>>> dict_intersection(*dicts)
{"a": 3}
我觉得应该有一种优雅的方式来编写dict_intersection
,但我自己只提出了不雅观和/或低效的解决方案。建议
>>> dict(set.intersection(*(set(d.iteritems()) for d in dicts)))
{'a': 3}
注意:此解决方案要求除键外,字典值还可以散列。稍微脏一点的方法:获取每个字典的键列表,对每个列表进行排序,然后像合并它们一样继续操作(为每个列表保留索引,将一个索引与最低值一起前进)。每当所有索引指向同一个键时,检查值是否相等;无论哪种方式,都要提前所有索引。因为键/值对必须已经在第一个dict中,所以您可以迭代该dict的项
>>> 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}
dict(pair for pair in dicts[0].items()
if all((pair in d.items() for d in dicts[1:])))
看起来不像interjay的答案那么优雅,但是没有哈希值的限制
编辑:将all
表达式更改为发电机表达式以提高速度这是怎么回事
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}
您忘记了示例中的字符串文字引号。;)有趣的问题-我会仔细考虑这个问题,然后再回来。当然,到目前为止,你有什么收获?@Li aung:像类一样实例化
dict
时,不需要字符串文字引号。我发现这是一条避免那些讨厌的引语的非常方便的捷径。@lazyr:嘿,你每天都能学到东西!有趣的是一个类似的问题:至少在一个字典中没有差异。+1我认为这非常优雅,因为它适用于非散列。@jamylak如何在dict列表中使用它,其中的值是非散列的。上面这一条只适用于在列表中的第一条和另一条中查找常见项。好吧,你已经打败我了。再次证明集合交叉操作最好使用set
操作执行概念上很优雅,但排序似乎很昂贵。看起来您还需要很多“管道”代码(尽管明智地使用itertools
可能会有所帮助)defined@learnningprogramming如果您使用的是Python 3,reduce()
现在是import functools
,functools.reduce()
。