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()
提供的唯一(非私有)方法!