python中的成员资格测试比set()更快

python中的成员资格测试比set()更快,python,performance,set,fastq,Python,Performance,Set,Fastq,我必须检查包含10-100k这些元素的列表中是否存在数百万个元素(20-30个字母str)。在python中有没有比set()更快的方法 set的速度是最快的 但是,如果您将代码重写一次以创建集,而不进行更改,则可以使用冻结集内置类型。它完全一样,只是不可变 如果您仍然存在速度问题,则需要以其他方式加快程序的速度,例如使用而不是cPython。您应该尝试分割数据以加快搜索速度。树结构允许您快速查找数据是否存在 例如,从一个简单的映射开始,该映射将第一个字母与以该字母开头的所有键链接起来,因此您不

我必须检查包含10-100k这些元素的列表中是否存在数百万个元素(20-30个字母str)。在python中有没有比
set()
更快的方法


set
的速度是最快的

但是,如果您将代码重写一次以创建
,而不进行更改,则可以使用
冻结集
内置类型。它完全一样,只是不可变


如果您仍然存在速度问题,则需要以其他方式加快程序的速度,例如使用而不是cPython。

您应该尝试分割数据以加快搜索速度。树结构允许您快速查找数据是否存在

例如,从一个简单的映射开始,该映射将第一个字母与以该字母开头的所有键链接起来,因此您不必搜索所有键,只需搜索其中的一小部分

这看起来像:

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 )
创建会稍微慢一点,但搜索速度应该快得多(如果密钥的第一个字符分布均匀且不总是相同的话,我预计会快20倍)


这是第一步,您可以对第二个字符执行相同的操作,依此类推,然后搜索将只是带着每个字母在树上行走…

正如我在评论中指出的,可能会减慢您的速度的是,您正在顺序检查来自
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)

在我5年的机器上,上面的代码只需6秒,它正在测试比你需要的更大的集合中的成员身份(除非我误解了你)。大部分时间实际上是用来创建集合的,所以你甚至不会有这样的开销。您所指的字符串很长这一事实在这里并不相关;正如agf所解释的,创建一个集合将创建一个哈希表。我怀疑(尽管你的问题也不清楚),如果你能在做任何成员资格测试之前将所有输入数据输入到一个集合中,速度会快得多,而不是像urschrei提到的那样一次读取一个项目,然后检查集合成员资格,你应该“矢量化”检查。
一次检查一百万个元素的存在比一百万次检查一个元素要快

你实际得到的时间是多少?60秒,C++中的一个算法(使用Tr1/unOrdEdSeToT)在18秒中也一样……你必须依次检查吗?创建两个集合,创建一个交集,然后从检查成员资格的集合中减去交集可能会更快。这是非常模糊的。你需要给出一个可以重复运行的结果,人们可以实际运行。我刚刚看到了你的评论——Python的速度大约是C++的3倍。对于Python来说,这在很多方面都非常好。您分析过Python代码吗?检查集合成员身份的时间占多大百分比,做其他事情的时间占多大百分比?PyPy比cPython快多少?。基本上,它实现了一个即时编译器,就像浏览器中的JavaScript引擎一样,可以极大地提高许多类型代码的速度。在大多数情况下,它的速度要快2-100倍。你分析过你的代码吗?是
\uuuu包含的步骤占用了大部分时间吗?正如我在回答中所说,“
set
的速度是最快的。”除非你的问题在别处,否则在Python中无法提高速度。在我的代码(无关项目)中,使用fozenset()而不是set()将速度提高了15%。@ChaimG根据这个回答,set和frozenset的速度应该是完全相同的——好奇你是如何测试它的,它有什么不同?set访问是O(1),一棵树如何使它更快?嗯,你似乎是对的。我的错误今天我真的学到了一些重要的东西,我认为集合只是一个没有两倍相同值的列表。你有什么网址可以让我找到更多的信息吗?我在官方文档中找不到关于访问速度的任何信息。请看一下,这就是集合和字典的含义。@JC Plessis:请看一下详细的python操作复杂性:
#!/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)