Python 检查两个词典是否不相交
有没有比计算两个字典的交集更容易/更快的方法来确定两个字典是否不相交 对于我找到的交叉点,不相交测试如下所示:Python 检查两个词典是否不相交,python,dictionary,set-intersection,disjoint-sets,Python,Dictionary,Set Intersection,Disjoint Sets,有没有比计算两个字典的交集更容易/更快的方法来确定两个字典是否不相交 对于我找到的交叉点,不相交测试如下所示: 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):
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)
或:
两者都将短路。编辑为仅显示方法和计时 由于OP询问了执行此操作的最快方法,我根据(我希望)在我的机器上进行的公平测试对讨论中的方法进行了排名。其目的是找出字典的键是否是不相交的,并且似乎
dict_keys.isdisjoint()
方法比其他集合或列表操作更有效
然而,正如在其他答案中提到的,这将根据相关词典的大小以及它们是否不相交而有很大的不同
这些测试仅适用于两个大小相等(较小)的不相交字典
最快:dict\u keys.isdisjoint()
例如:
{"a": 1, "b": 2, "c": 3 }.keys().isdisjoint({ "d": 4, "e": 5, "f": 6}.keys())
set({"a": 1, "b": 2, "c": 3 }.keys()).isdisjoint(set({ "d": 4, "e": 5, "f": 6}.keys()))
all(k not in {"a": 1, "b": 2, "c": 3 } for k in { "d": 4, "e": 5, "f": 6})
not set({"a": 1, "b": 2, "c": 3 }.keys()) ^ set({ "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()
例如:
{"a": 1, "b": 2, "c": 3 }.keys().isdisjoint({ "d": 4, "e": 5, "f": 6}.keys())
set({"a": 1, "b": 2, "c": 3 }.keys()).isdisjoint(set({ "d": 4, "e": 5, "f": 6}.keys()))
all(k not in {"a": 1, "b": 2, "c": 3 } for k in { "d": 4, "e": 5, "f": 6})
not set({"a": 1, "b": 2, "c": 3 }.keys()) ^ 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
>>> timeit.timeit('all(k not in {"a": 1, "b": 2, "c": 3 } for k in { "d": 4, "e": 5, "f": 6})')
0.8577601349970791
>>> timeit.timeit('not set({"a": 1, "b": 2, "c": 3 }.keys()) ^ set({ "d": 4, "e": 5, "f": 6}.keys())')
0.9617313010094222
第三快:列出Comp和all()
:
例如:
{"a": 1, "b": 2, "c": 3 }.keys().isdisjoint({ "d": 4, "e": 5, "f": 6}.keys())
set({"a": 1, "b": 2, "c": 3 }.keys()).isdisjoint(set({ "d": 4, "e": 5, "f": 6}.keys()))
all(k not in {"a": 1, "b": 2, "c": 3 } for k in { "d": 4, "e": 5, "f": 6})
not set({"a": 1, "b": 2, "c": 3 }.keys()) ^ 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
>>> timeit.timeit('all(k not in {"a": 1, "b": 2, "c": 3 } for k in { "d": 4, "e": 5, "f": 6})')
0.8577601349970791
>>> timeit.timeit('not set({"a": 1, "b": 2, "c": 3 }.keys()) ^ set({ "d": 4, "e": 5, "f": 6}.keys())')
0.9617313010094222
第四快:对称差异(^
)与非()
例如:
{"a": 1, "b": 2, "c": 3 }.keys().isdisjoint({ "d": 4, "e": 5, "f": 6}.keys())
set({"a": 1, "b": 2, "c": 3 }.keys()).isdisjoint(set({ "d": 4, "e": 5, "f": 6}.keys()))
all(k not in {"a": 1, "b": 2, "c": 3 } for k in { "d": 4, "e": 5, "f": 6})
not set({"a": 1, "b": 2, "c": 3 }.keys()) ^ 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
>>> timeit.timeit('all(k not in {"a": 1, "b": 2, "c": 3 } for k in { "d": 4, "e": 5, "f": 6})')
0.8577601349970791
>>> timeit.timeit('not set({"a": 1, "b": 2, "c": 3 }.keys()) ^ set({ "d": 4, "e": 5, "f": 6}.keys())')
0.9617313010094222
不要转换成一个集合;dict\u keys
对象已支持isdisjoint
d1.keys().isdisjoint(d2)
它可能更容易理解为all(k不在b中表示k在a中)
。我总是必须阅读而不是任何
s两次XD您确定这比设置交叉点更快(如OP所愿)?@randomir由于短路和dicts的任意性,很难说。这是一个统计问题。不管它值多少钱,我相信它会更快。这取决于dict的大小,对于较小的dict,它会更快。两者都是O(n)
,但是集合交集将具有C
的优点,可以克服set()
结构,前提是大多数是不相交的。这很整洁,我喜欢这是-当然,如果你只是想看看是否没有共享键。而不是bool(x)
只是而不是x
。使用set
进行转换既浪费时间又不会短路<代码>^
不会短路。这一点很好@Veedrac-虽然我有时编写bool()
以帮助可读性,但删除它会大大加快脚本的速度。不知道你说的短路是什么意思?据我所知,此操作仅适用于集合…您的第三次测试不是有效的比较。您将使用dict而不是list,并且k not in list
以线性时间运行,而k not in dict
取常数。因此,它高度依赖于输入大小。谢谢-我对它进行了编辑,以反映所有方法的公平时间安排。+1,仅Python 3,但我不知道这一点,它似乎是.keys()
提供的唯一(非私有)方法!