我必须在包含10-100k这些元素的列表中检查数百万个元素(20-30个字母str)的存在。在python中执行此操作的方法是否比set()
更快?
import sys
#load ids
ids = set( x.strip() for x in open(idfile) )
for line in sys.stdin:
id=line.strip()
if id in ids:
#print fastq
print id
#update ids
ids.remove( id )
答案 0 :(得分:25)
set
和它一样快。
但是,如果您重写代码以创建set
一次,而不是更改它,则可以使用frozenset
内置类型。除了不可变之外,它完全相同。
如果您仍然遇到速度问题,则需要以其他方式加快程序速度,例如使用PyPy代替cPython。
答案 1 :(得分:10)
正如我在评论中所指出的那样,可能会减慢您的速度,因为您要按顺序检查sys.stdin
中的每一行是否为“主”集的成员资格。这将非常非常慢,并且不允许您利用设置操作的速度。举个例子:
#!/usr/bin/env python
import random
# create two million-element sets of random numbers
a = set(random.sample(xrange(10000000),1000000))
b = set(random.sample(xrange(10000000),1000000))
# a intersection b
c = a & b
# a difference c
d = list(a - c)
print "set d is all remaining elements in a not common to a intersection b"
print "length of d is %s" % len(d)
以上在我五岁的机器上以6秒钟的时间内运行,它正在测试比你需要的更大的成员资格(除非我误解了你)。大部分时间实际上是创建集合,所以你甚至不会有这个开销。你引用的字符串很长的事实与此无关;正如agf解释的那样,创建一个集合会创建一个哈希表。我怀疑(尽管从你的问题中再说不清楚)如果你可以在之前将所有输入数据放到集合中进行任何成员资格测试,那么它会快得多,而不是一次读取一个项目,然后检查设置成员资格
答案 2 :(得分:0)
您应该尝试拆分数据以加快搜索速度。树形结构可以让您快速找到数据是否存在。
例如,从一个简单的地图开始,该地图将第一个字母与以该字母开头的所有键相关联,因此您不必搜索所有键,只需搜索其中的一小部分。
这看起来像是:
ids = {}
for id in open(idfile):
ids.setdefault(id[0], set()).add(id)
for line in sys.stdin:
id=line.strip()
if id in ids.get(id[0], set()):
#print fastq
print id
#update ids
ids[id[0]].remove( id )
创建会慢一点,但搜索速度要快得多(如果你的密钥的fisrt字符分布均匀并且并不总是相同的话,我希望速度提高20倍。)
这是第一步,您可以使用第二个字符执行相同操作,依此类推,搜索只会在每个字母的树上行走......
答案 3 :(得分:-2)
正如urschrei所提到的,你应该“检查”支票。 检查一百万个元素的存在(如在C中完成)比检查一个元素一百万次更快。