检查一个值是否存在于一个非常大的列表的最快方法是什么?
当前回答
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()部分,然后重复使用它。如果a确实发生了变化,请提供更多关于您正在做什么的细节。
其他回答
你可以把你的物品放在一个集合里。设置查找非常有效。
Try:
s = set(a)
if 7 in s:
# do stuff
在注释中,你说你想获取元素的索引。不幸的是,集合没有元素位置的概念。另一种方法是对列表进行预先排序,然后在每次需要查找元素时使用二分搜索。
听起来您的应用程序可能会从使用Bloom Filter数据结构中获得优势。
简而言之,bloom过滤器查找可以非常快速地告诉你一个值是否绝对不存在于一个集合中。否则,您可以执行较慢的查找,以获得可能在列表中的值的索引。因此,如果您的应用程序倾向于获得“未找到”结果,而不是“找到”结果,您可能会通过添加Bloom Filter看到速度的提高。
关于细节,维基百科提供了Bloom过滤器如何工作的很好的概述,在网上搜索“python Bloom过滤器库”将提供至少两个有用的实现。
如果您只想检查列表中是否存在一个元素,
7 in list_data
是最快的解决方案。请注意
7 in set_data
是一个近乎自由的操作,与集合的大小无关!从一个大列表中创建一个set要比在列表中慢300到400倍,所以如果您需要检查许多元素,首先创建一个set会更快。
用perfplot创建的Plot:
import perfplot
import numpy as np
def setup(n):
data = np.arange(n)
np.random.shuffle(data)
return data, set(data)
def list_in(data):
return 7 in data[0]
def create_set_from_list(data):
return set(data[0])
def set_in(data):
return 7 in data[1]
b = perfplot.bench(
setup=setup,
kernels=[list_in, set_in, create_set_from_list],
n_range=[2 ** k for k in range(24)],
xlabel="len(data)",
equality_check=None,
)
b.save("out.png")
b.show()
这不是代码,而是快速搜索的算法。
如果您的列表和您正在寻找的值都是数字,这是相当简单的。如果字符串:看底部:
-Let "n" be the length of your list -Optional step: if you need the index of the element: add a second column to the list with current index of elements (0 to n-1) - see later Order your list or a copy of it (.sort()) Loop through: Compare your number to the n/2th element of the list If larger, loop again between indexes n/2-n If smaller, loop again between indexes 0-n/2 If the same: you found it Keep narrowing the list until you have found it or only have 2 numbers (below and above the one you are looking for) This will find any element in at most 19 steps for a list of 1.000.000 (log(2)n to be precise)
如果您还需要您的数字的原始位置,请在第二索引列中查找。
如果您的列表不是由数字组成的,该方法仍然有效,并且将是最快的,但您可能需要定义一个可以比较/排序字符串的函数。
当然,这需要使用sorted()方法,但如果您不断重用相同的列表进行检查,那么这样做可能是值得的。
7 in a
最清晰最快的方法。
您也可以考虑使用一个集合,但是从列表中构造该集合所花费的时间可能比快速成员测试所节省的时间要多。唯一确定的方法就是做好基准测试。(这也取决于你需要什么操作)