Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python:只查找几个dict的公共键值对:dict交集_Python - Fatal编程技术网

python:只查找几个dict的公共键值对: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,但我自己只提出了不雅观和/或低

我在列表中有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
,但我自己只提出了不雅观和/或低效的解决方案。建议

>>> 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()