如何检查某个值是否存在于任何给定集合中

2024-03-12

假设我有不同的集合(它们必须不同,我无法根据我正在使用的数据类型加入它们):

r = set([1,2,3])
s = set([4,5,6])
t = set([7,8,9])

检查给定变量是否存在于其中任何一个中的最佳方法是什么?

我在用:

if myvar in r \
   or myvar in s \
   or myvar in t:

但我想知道是否可以通过使用以某种方式减少这种情况set的属性如union.

以下有效,但我找不到定义多个联合的方法:

if myvar in r.union(s)
   or myvar in t:

我也想知道这个联盟是否会以某种方式影响性能,因为我猜是暂时的set将即时创建。


只需使用任何:

if any(myvar in x for x in  (r,s,t))

设置查找是0(1)因此,创建一个联合来检查变量是否在任何集合中是完全没有必要的,而不是简单地使用检查in with any一旦找到匹配,它就会短路,并且不会创建新的集合。

我也想知道这个联盟是否会以某种方式影响性能

是的,当然联合集合会影响性能,它会增加复杂性,您每次都会创建一个新集合O(len(r)+len(s)+len(t))所以你可以告别使用高效查找集的真正意义。

因此,最重要的是,您想要保持高效的查找,您必须将集合合并一次并将它们保留在内存中,创建一个新变量,然后使用它来查找myvar所以最初的创建将是0(n)查找将是0(1)此后。

如果您不是每次都想首先创建并集进行查找,您将得到长度为的线性解决方案r+s+t -> set.union(*(r, s, t))与最坏情况下的三个恒定(平均)查找相反。这也意味着始终从新的联合集中添加或删除任何元素r,s or t.

中等规模的集合上的一些实际计时显示了确切的差异:

In [1]: r = set(range(10000))

In [2]: s = set(range(10001,20000))

In [3]: t = set(range(20001,30000))

In [4]: timeit any(29000 in st for st in (r,s,t))
1000000 loops, best of 3: 869 ns per loop  

In [5]: timeit 29000 in r | s | t
1000 loops, best of 3: 956 µs per loop

In [6]: timeit 29000 in reduce(lambda x,y :x.union(y),[r,s,t])
1000 loops, best of 3: 961 µs per loop

In [7]: timeit 29000 in r.union(s).union(t)
1000 loops, best of 3: 953 µs per loop

对联合进行计时表明,几乎所有时间都花在了联合调用上:

In [8]: timeit r.union(s).union(t)
1000 loops, best of 3: 952 µs per loop

使用更大的集合并获取最后一个集合中的元素:

In [15]: r = set(range(1000000))

In [16]: s = set(range(1000001,2000000))

In [17]: t = set(range(2000001,3000000))


In [18]: timeit any(2999999 in st for st in (r,s,t))
1000000 loops, best of 3: 878 ns per loop

In [19]: timeit 2999999 in reduce(lambda x,y :x.union(y),[r,s,t])
1 loops, best of 3: 161 ms per loop

In [20]: timeit 2999999 in r | s | t
10 loops, best of 3: 157 ms per loop

无论使用多大的集合,实际上都没有区别any但随着集合大小的增加,使用 union 的运行时间也会增加。

让它更快的唯一方法是坚持or但我们采用了几百纳秒的差异,这是创建生成器表达式和函数调用的成本:

In [22]: timeit 2999999 in r or 2999999 in s or 2999999 in t
10000000 loops, best of 3: 152 ns per loop

联合集 set.union(*(r, s, t)) 也是最快的,因为您不构建中间集:

In [47]: timeit 2999999 in set.union(*(r,s,t))
10 loops, best of 3: 108 ms per loop
In [49]: r | s | t  == set.union(*(r,s,t))
Out[49]: True
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何检查某个值是否存在于任何给定集合中 的相关文章

随机推荐