【发布时间】:2015-04-02 00:08:40
【问题描述】:
我知道搜索的简单方法是创建一个包含字符串的列表,然后执行if string in list,但它会变慢,而且我听说字典键实际上不会因为大集合而减速它们没有被订购。
但是,我不需要任何与项目相关的额外信息,所以制作字典只是为了保存键并将值设置为 None 感觉有点不对。
有什么我可以使用的东西在速度方面像字典键一样,但又像一个列表?
这是一个简单的例子:
import time, random
totalRange = 100000
searchFor = 5000
#Create a list of 10 million characters
searchableList = []
for i in range( totalRange ):
searchableList.append( random.randint( 0, totalRange ) )
#Create dictonary with keys set to 'None'
searchableDict = {}
for i in searchableList:
searchableDict[i] = None
searchableSet = set( searchableList )
#Search list
startTime = time.time()
numberMatches = 0
for number in range( searchFor ):
if number in searchableList:
numberMatches += 1
print numberMatches, time.time()-startTime
#Search dictionary keys
startTime = time.time()
numberMatches = 0
for number in range( searchFor ):
if number in searchableDict:
numberMatches += 1
print numberMatches, time.time()-startTime
#Search set
startTime = time.time()
numberMatches = 0
for number in range( searchFor ):
if number in searchableSet:
numberMatches += 1
print numberMatches, time.time()-startTime
以下是时间输出:
List: 18.8 seconds
Set: 0.002 seconds
Dictionary: 0.0009 seconds
尽管 set 比 list 快很多,但字典仍然快两倍,所以我想知道是否还有什么我不知道的。使用字典不会太糟糕,我只是想有一种比dictionary[key]=None 更清洁的方法。
根据 iCodez 的回答进行编辑:
在 totalRange=1000000 和 searchFor=50000(高 10 倍)时进行测试:
List = 20 minutes and still going
Dictionary = 0.023 seconds
Set = 0.02 seconds
Set.intersection = 0.008 seconds
随着计算次数的增加,似乎集合和字典的效率非常相似,但set.intersetion 的方式显然要好得多。
【问题讨论】:
-
最干净、最清晰、最明显的方法是使用集合。不幸的是,您当前的实现似乎对此有轻微的惩罚,但看起来并没有那么担心。如果你能容忍一点模糊,布隆过滤器可能是一个不错的选择。
-
使用一套。您的时差可以忽略不计,它在概念上是正确的数据结构。
-
.002 vs .0009 太小了,无法真正说出哪个更快。这完全在您正在使用的计时器的限制范围内。
-
你应该在这样的小时候使用 timeit 模块...
-
FWIW 我刚刚做的一些 timeit 测试有 sets 稍微快一些。但是,如果 Joran 对
set.intersection的建议还没有快很多(以内存换取速度),我会感到非常惊讶。
标签: python