Kru*_*pös 4 python algorithm dictionary python-3.x
我想找到一种简单和/或快速的方法来查找在python中给出N个字典的所有普通情侣(对:值).(3.X会是最好的)
问题
给定一组3 dicts(但它可以是任何一个dict,它仅用于示例)
n1 = {'a': 1, 'b': 2, 'c': 3}
n2 = {'a': 1, 'b': 4, 'c': 3, 'd': 4}
n3 = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
Run Code Online (Sandbox Code Playgroud)
共同结果(键:值)n1,n2而n3
应该是:
({'a': 1, 'c': 3})
Run Code Online (Sandbox Code Playgroud)
而对于n2和n3它应该是
({'a': 1, 'c': 3, 'd': 4})
Run Code Online (Sandbox Code Playgroud)
我首先考虑使用强力算法来检查每个字典的每一对(键:值)
这是使用递归算法的实现
解决方案A.
list_dict = [n1, n2, n3]
def finding_uniquness(ls):
def recursion(ls, result):
if not ls:
return result
result = {k: v for k, v in result.items() for k1, v1 in ls[0].items() if k == k1 and v == v1}
return recursion(ls[1:], result)
return recursion(ls[1:], ls[0])
finding_uniquness(list_dict)
# {'c': 3, 'a': 1}
Run Code Online (Sandbox Code Playgroud)
但它不容易理解,而且复杂性很高(我不确定如何计算复杂性;但是由于我们比较了所有元素dict,复杂性应该是O(N²)?)
然后,我虽然Sets.因为它可以自然地比较所有元素
解决方案B.
import functools
list_dict = [n1, n2, n3]
set_list = [set(n.items()) for n in list_dict]
functools.reduce(lambda x, y: x & y, set_list)
# {('a', 1), ('c', 3)}
Run Code Online (Sandbox Code Playgroud)
它比以前的解决方案好得多,不幸的是,当其中一个key具有listas值时会抛出错误:
>>> n = {'a': [], 'b': 2, 'c': 3}
>>> set(n.items())
Run Code Online (Sandbox Code Playgroud)
TypeError:不可用类型:'list'
我的问题是双重的:
TypeError使用解决方案B?当然,欢迎任何其他言论.
更简单,更有效的方式:
>>> {k: v
for k, v in list_dict[0].items()
if all(k in d and d[k] == v
for d in list_dict[1:])}
{'c': 3, 'a': 1}
Run Code Online (Sandbox Code Playgroud)
使用额外的变量list_dict[1:]可能是有益的,否则短路会all有些浪费.或者,如果您之后不需要列表,则可以弹出"主"字典:
>>> {k: v
for k, v in list_dict.pop().items()
if all(k in d and d[k] == v
for d in list_dict)}
{'c': 3, 'a': 1}
Run Code Online (Sandbox Code Playgroud)
或使用get@ Jean-FrançoisFabre建议的不能在字典中的默认值:
>>> marker = object()
>>> {k: v
for k, v in list_dict.pop().items()
if all(d.get(k, marker) == v
for d in list_dict)}
{'c': 3, 'a': 1}
Run Code Online (Sandbox Code Playgroud)