只需使用任何:
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