检查两个字典是否不相交
Check if two dictionaries are disjoint
有没有 easier/faster 方法可以找出两个字典是否不相交而不是计算它们的交集?
对于我找到的交集 this answer,因此不相交测试将如下所示:
def dicts_disjoint(a, b):
keys_a = set(a.keys())
keys_b = set(b.keys())
intersection = keys_a & keys_b
return not len(intersection)
但是我认为这是低效的,因为它总是计算整个路口(没有短路退出)。
有更好的主意吗?
您是否在寻找类似的东西:
def dicts_disjoint(a, b):
return not any(k in b for k in a)
或者:
def dicts_disjoint(a, b):
return all(k not in b for k in a)
两者都会短路
编辑为仅显示方法和时间
由于 OP 询问执行此操作的最快方法,我根据(我希望)在我的机器上进行的公平测试对正在讨论的方法进行了排名。目的是查找字典的键是否不相交,并且 dict_keys.isdisjoint()
方法似乎胜过其他集合或列表操作。
但是,正如其他答案中提到的,这将根据相关词典的大小以及它们是否不相交而有很大差异。
这些测试仅适用于大小相等(小)的两个不相交的词典。
最快:dict_keys.isdisjoint()
示例:
{"a": 1, "b": 2, "c": 3 }.keys().isdisjoint({ "d": 4, "e": 5, "f": 6}.keys())
时间:
>>> timeit.timeit('{"a": 1, "b": 2, "c": 3 }.keys().isdisjoint({ "d": 4, "e": 5, "f": 6}.keys())')
0.4637166199972853
第二快:set.isdisjoint()
示例:
set({"a": 1, "b": 2, "c": 3 }.keys()).isdisjoint(set({ "d": 4, "e": 5, "f": 6}.keys()))
时间:
>>> timeit.timeit('set({"a": 1, "b": 2, "c": 3 }.keys()).isdisjoint(set({ "d": 4, "e": 5, "f": 6}.keys()))')
0.774243315012427
第三快:列出 Comp 和 all()
:
示例:
all(k not in {"a": 1, "b": 2, "c": 3 } for k in { "d": 4, "e": 5, "f": 6})
时间:
>>> timeit.timeit('all(k not in {"a": 1, "b": 2, "c": 3 } for k in { "d": 4, "e": 5, "f": 6})')
0.8577601349970791
第四快:对称差异 (^
) 与 not()
示例:
not set({"a": 1, "b": 2, "c": 3 }.keys()) ^ set({ "d": 4, "e": 5, "f": 6}.keys())
时间:
>>> timeit.timeit('not set({"a": 1, "b": 2, "c": 3 }.keys()) ^ set({ "d": 4, "e": 5, "f": 6}.keys())')
0.9617313010094222
不要转换为集合; dict_keys
对象已经支持 isdisjoint
.
d1.keys().isdisjoint(d2)
仅使用位运算:
变量
dict1 = {"a":1, "b":2}
dict2 = {"a":4, "c":2}
联盟
dict1.keys() | dict2.keys()
# {'b', 'a', 'c'}
路口
dict1.keys() & dict2.keys()
# {'a'}
不相交
dict1.keys() ^ dict2.keys()
# {'b', 'c'}
然后设置一个条件:
"different" if dict1.keys() ^ dict2.keys() else "equal"
空集() return布尔条件下的“假”
有没有 easier/faster 方法可以找出两个字典是否不相交而不是计算它们的交集?
对于我找到的交集 this answer,因此不相交测试将如下所示:
def dicts_disjoint(a, b):
keys_a = set(a.keys())
keys_b = set(b.keys())
intersection = keys_a & keys_b
return not len(intersection)
但是我认为这是低效的,因为它总是计算整个路口(没有短路退出)。
有更好的主意吗?
您是否在寻找类似的东西:
def dicts_disjoint(a, b):
return not any(k in b for k in a)
或者:
def dicts_disjoint(a, b):
return all(k not in b for k in a)
两者都会短路
编辑为仅显示方法和时间
由于 OP 询问执行此操作的最快方法,我根据(我希望)在我的机器上进行的公平测试对正在讨论的方法进行了排名。目的是查找字典的键是否不相交,并且 dict_keys.isdisjoint()
方法似乎胜过其他集合或列表操作。
但是,正如其他答案中提到的,这将根据相关词典的大小以及它们是否不相交而有很大差异。
这些测试仅适用于大小相等(小)的两个不相交的词典。
最快:dict_keys.isdisjoint()
示例:
{"a": 1, "b": 2, "c": 3 }.keys().isdisjoint({ "d": 4, "e": 5, "f": 6}.keys())
时间:
>>> timeit.timeit('{"a": 1, "b": 2, "c": 3 }.keys().isdisjoint({ "d": 4, "e": 5, "f": 6}.keys())')
0.4637166199972853
第二快:set.isdisjoint()
示例:
set({"a": 1, "b": 2, "c": 3 }.keys()).isdisjoint(set({ "d": 4, "e": 5, "f": 6}.keys()))
时间:
>>> timeit.timeit('set({"a": 1, "b": 2, "c": 3 }.keys()).isdisjoint(set({ "d": 4, "e": 5, "f": 6}.keys()))')
0.774243315012427
第三快:列出 Comp 和 all()
:
示例:
all(k not in {"a": 1, "b": 2, "c": 3 } for k in { "d": 4, "e": 5, "f": 6})
时间:
>>> timeit.timeit('all(k not in {"a": 1, "b": 2, "c": 3 } for k in { "d": 4, "e": 5, "f": 6})')
0.8577601349970791
第四快:对称差异 (^
) 与 not()
示例:
not set({"a": 1, "b": 2, "c": 3 }.keys()) ^ set({ "d": 4, "e": 5, "f": 6}.keys())
时间:
>>> timeit.timeit('not set({"a": 1, "b": 2, "c": 3 }.keys()) ^ set({ "d": 4, "e": 5, "f": 6}.keys())')
0.9617313010094222
不要转换为集合; dict_keys
对象已经支持 isdisjoint
.
d1.keys().isdisjoint(d2)
仅使用位运算: 变量
dict1 = {"a":1, "b":2}
dict2 = {"a":4, "c":2}
联盟
dict1.keys() | dict2.keys()
# {'b', 'a', 'c'}
路口
dict1.keys() & dict2.keys()
# {'a'}
不相交
dict1.keys() ^ dict2.keys()
# {'b', 'c'}
然后设置一个条件:
"different" if dict1.keys() ^ dict2.keys() else "equal"
空集() return布尔条件下的“假”