最快的方法来检查列表中是否存在一个值
我正在寻找最快的方法来知道一个列表中是否存在一个值(一个有数百万个值的列表)以及它的索引是什么? 我知道列表中的所有值都是独特的,就像我的例子。
我尝试的第一种方法是(在我的真实代码中为3.8秒):
a = [4,2,3,1,5,6] if a.count(7) == 1: b=a.index(7) "Do something with variable b"
我尝试的第二种方法是(快两倍:我的真实代码1.9秒):
a = [4,2,3,1,5,6] try: b=a.index(7) except ValueError: "Do nothing" else: "Do something with variable b"
来自Stackoverflow用户的build议方法(在我的真实代码上2.74秒):
a = [4,2,3,1,5,6] if 7 in a: a.index(7)
在我的实际代码中,第一个方法需要3.81秒,第二个方法需要1.88秒。 这是一个很好的改进,但是:
我是一个Python /脚本编程的初学者,我想知道是否有最快的方法来做同样的事情,并节省更多的处理时间?
我的应用程序更具体的说明:
在搅拌机的API中,可以访问粒子列表:
particles = [1,2,3,4...etc.]
从那里,我可以访问它的位置:
particles[x].location = [x,y,z]
而且我通过search每个粒子的位置来testing每个粒子是否存在邻居:
if [x+1,y,z] in particles.location "find the identity of this neighbour particles in x:the index of the particles array" particles.index([x+1,y,z])
7 in a
最清楚,最快速的方式来做到这一点。
您也可以考虑使用一个set
,但是从列表中构build该集合可能需要更多的时间,而更快的成员资格testing将会节省。 要确定的唯一方法就是做好基准。 (这也取决于你需要什么操作)
正如其他人所说, in
大型列表中速度可能会非常慢。 这里是一些比较的performance, in
, set
bisect
。 注意时间(秒)是以对数为单位。
testing代码:
import random import bisect import matplotlib.pyplot as plt def method_in(a,b,c): start_time = time.time() for i,x in enumerate(a): if x in b: c[i] = 1 return(time.time()-start_time) def method_set_in(a,b,c): start_time = time.time() s = set(b) for i,x in enumerate(a): if x in s: c[i] = 1 return(time.time()-start_time) def method_bisect(a,b,c): start_time = time.time() b.sort() for i,x in enumerate(a): index = bisect.bisect_left(b,x) if index < len(a): if x == b[index]: c[i] = 1 return(time.time()-start_time) def profile(): time_method_in = [] time_method_set_in = [] time_method_bisect = [] Nls = [x for x in range(1000,20000,1000)] for N in Nls: a = [x for x in range(0,N)] random.shuffle(a) b = [x for x in range(0,N)] random.shuffle(b) c = [0 for x in range(0,N)] time_method_in.append(math.log(method_in(a,b,c))) time_method_set_in.append(math.log(method_set_in(a,b,c))) time_method_bisect.append(math.log(method_bisect(a,b,c))) plt.plot(Nls,time_method_in,marker='o',color='r',linestyle='-',label='in') plt.plot(Nls,time_method_set_in,marker='o',color='b',linestyle='-',label='set') plt.plot(Nls,time_method_bisect,marker='o',color='g',linestyle='-',label='bisect') plt.xlabel('list size', fontsize=18) plt.ylabel('log(time)', fontsize=18) plt.legend(loc = 'upper left') plt.show()
a = [1,2,3,4,'a','b','c'] return 'a' in a
用这个你可以在数组中find你想要的值。 这是知道所选值是否在数组中的最快方法。
你可以把你的物品放入一个set
。 设置查找是非常有效的。
尝试:
s = set(a) if 7 in s: # do stuff
编辑在评论中,你说你想获得元素的索引。 不幸的是,集合没有元素位置的概念。 另一种方法是预先对列表进行sorting,然后在每次需要查找元素时使用二进制search 。
a = [4,2,3,1,5,6] index = dict((y,x) for x,y in enumerate(a)) try: a_index = index[7] except KeyError: print "Not found" else: print "found"
如果a不改变,这只是一个好主意,因此我们可以做一次dict()部分,然后重复使用它。 如果确实有变化,请提供更多关于你在做什么的细节。
这听起来像你的应用程序可能会从使用Bloom Filter数据结构中获得优势。
总之,布隆filter查找可以很快地告诉你,如果一个值是一个集合中DEFINITELY不存在。 否则,你可以做一个较慢的查找来得到一个值可能在列表中的索引。 因此,如果您的应用程序往往会更频繁地得到“未find”结果,那么“find”结果,您可能会看到通过添加Bloom Filter来加速。
有关详细信息,Wikipedia提供了有关Bloom Filters如何工作的良好概述,而对“python bloom filter库”的networkingsearch将提供至less一些有用的实现。
这不是代码,而是非常快的searchalgorithm
如果你的列表和你正在寻找的值都是数字,这是非常简单的,如果string:看底部:
- -let“n”是你列表的长度
- – 可选步骤:如果你需要元素的索引:添加第二列到元素的当前索引(0到n-1)的列表中 – 稍后参考
- 订购您的清单或其副本(.sort())
- 循环:
- 将您的号码与列表的第n / 2个元素进行比较
- 如果较大,则在索引n / 2-n之间再次循环
- 如果较小,则在索引0-n / 2之间再次循环
- 如果相同:你find了
- 将您的号码与列表的第n / 2个元素进行比较
- 不断缩小列表,直到find它或只有2个数字(低于和高于你正在查找的数字)
- 这将在1.000.000 (log(2)n) 列表中以最多19个步骤find任何元素,
如果您还需要您的号码的原始位置,请在第二个索引列中查找
如果你的列表不是由数字组成的,那么这个方法仍然可以工作,而且速度也是最快的,但是你可能需要定义一个函数来比较/sortingstring
当然这需要sort()方法的投资,但是如果你不断重复使用同一个列表进行检查,那么可能是值得的
尝试
n =0 while n <= 7: list_a = ['omar','loubna','najawa','mohamed','essa','ahmed'] x = input("Enter your name:") n = n+1 if x in list_a: print("ok") if x not in list_a: print("ValueError: ",x, "is not in list")