如何高效地检查一个字典的键值对是否也存在于另一个字典中。
假设我有两个名为dict1和dict2的字典,并且这两个字典有一些相同的键值对。我想找到它们并打印出来。最高效的方法是什么?请给予建议。
如何高效地检查一个字典的键值对是否也存在于另一个字典中。
假设我有两个名为dict1和dict2的字典,并且这两个字典有一些相同的键值对。我想找到它们并打印出来。最高效的方法是什么?请给予建议。
d_inter = dict([k, v for k, v in dict1.iteritems() if k in dict2 and dict2[k] == v])
另一个:
d_inter = dict(set(d1.iteritems()).intersection(d2.iteritems()))
for k,v in dict1.iteritems()
-> O(n)
- 然后我们检查该键是否在dict2中,if k in dict2 and dict2[k] == v
-> O(m)O(n+m)
->O(n)
2. 使用set
的解决方案:dict
转换为set
是O(n)
:
set(d1.iteritems())
->O(n)
set(d2.iteritems())
->O(m)
O(min(len(s), len(t))
或最坏情况下为O(n * m)
这使得全局最坏情况复杂度为O(2n*n*m)
,对于大小相同的字典可以视为O(n^3)
,因此方案1是最佳的
如果我们假设将dict
转换为集合是O(1)
(常数时间)
平均情况下为O(min(n,m))
,最坏情况下为O(n*m)
,那么在平均情况下方案2更好,因为O(n+m) > O(min(n,m))
。
dict2
,对于解决方案#2,将最小的字典命名为dict1
。
注意2016年:这个解决方案是为python2编写的。以下是使其准备好使用python3所需的更改:
items()
替换iteritems()
;{[k,v for … == v]}
;d.items()
返回dict_items
,它不再是可哈希的,因此你必须使用frozenset()
而不是{frozenset(d1.items()).intersection(d2.items())}
。关于...
matching_dict_values = {}
for key in dict1.keys():
if key in dict2.keys():
if dict1[key] == dict2[key]:
matching_dict_values[key]=dict1[key]
.iteritems()
并遵循了@DSM的建议不要使用.keys()
。请参阅我的答案以获取所有细节。 - zmo更新至@zmo的答案
解决方案1:
d_inter = {k:v for k, v in dict1.items() if k in dict2 and dict2[k] == v}
解决方案2:
d_inter = dict(set(dict1.items()).intersection(dict2.items()))
我不明白为什么你需要比这更高级的东西:
if all([testKey in dict1, testKey in dict2]) and dict1[testKey] == dict2[testKey]:
我们不必担心KeyError
,因为布尔测试会在and
之前失败(与一个不存在的键相关联的值将永远不会被测试)
因此,要获取完整的公共键值对列表,您可以执行以下操作:
for testKey in set(dict1.keys() + dict2.keys()):
if all([testKey in dict1, testKey in dict2]) and dict1[testKey] == dict2[testKey]:
commonDict[testKey] = dict1[testKey]
for testKey in dict1.keys()+dict2.keys(): ...
?! - zmoO(n*m*(n+m))
,在最坏情况下是 O(n3)
。 - zmo
2.86 us per loop
和集合:2.06 us per loop
。因此,set
更好(至少对于小字典而言)。+1set + iteritems
的用法。 - FallenAngelk in dict2
来加快你的第一次操作;在Python 2中,k in dict2.keys()
首先创建一个列表,然后必须逐个扫描。 - DSMO(m)
。 @DSM 知道真好,我一直认为两者是等价的,因此更喜欢使用.keys()
,因为“显式优于隐式” :-) - zmotuple()
代替。 - zmo