【发布时间】:2010-09-17 01:18:30
【问题描述】:
我想在 python 脚本中使用任何最快的方法过滤两个列表。为此,我使用了内置的filter() 方法。但它很慢而且花费了太多时间,因为我有很大的列表,我认为每个列表中有超过 500 万个项目,或者可能更多。
我不知道我会怎么做。请如果有人有想法或为它编写小功能。
【问题讨论】:
我想在 python 脚本中使用任何最快的方法过滤两个列表。为此,我使用了内置的filter() 方法。但它很慢而且花费了太多时间,因为我有很大的列表,我认为每个列表中有超过 500 万个项目,或者可能更多。
我不知道我会怎么做。请如果有人有想法或为它编写小功能。
【问题讨论】:
也许您的列表太大,无法存储在内存中,您会遇到thrashing。 如果源文件在文件中,则不需要一次将整个列表都放在内存中。尝试使用 itertools,例如:
from itertools import ifilter
def is_important(s):
return len(s)>10
filtered_list = ifilter(is_important, open('mylist.txt'))
请注意,ifilter 返回一个快速且内存高效的 iterator。
Generator Tricks 是 David M. Beazley 的教程,教授 generators 的一些有趣用途。
【讨论】:
在使用 C 之前,您可以尝试numpy。也许您可以将过滤变成数字运算。
【讨论】:
过滤器将创建一个新列表,因此如果您的原始列表很大,您最终可能会使用两倍的内存。 如果您只需要迭代处理结果,而不是将其用作真正的随机访问列表,则最好使用 ifilter 代替。即。
for x in itertools.ifilter(condition_func, my_really_big_list):
do_something_with(x)
其他速度提示是使用 python 内置函数,而不是您自己编写的函数。有一个 itertools.ifilterfalse 专门用于 否则您需要引入 lambda 来否定您的检查的情况。 (例如“ifilter(lambda x: not x.isalpha(), l)”应该写成“ifilterfalse(str.isalpha, l)”)
【讨论】:
知道条件列表推导通常比相应的 lambda 快得多,这可能很有用:
>>> import timeit
>>> timeit.Timer('[x for x in xrange(10) if (x**2 % 4) == 1]').timeit()
2.0544309616088867
>>> timeit.f = lambda x: (x**2 % 4) == 1
timeit.Timer('[x for x in xrange(10) if f(x)]').timeit()
>>>
3.4280929565429688
(不知道为什么我需要将 f 放在 timeit 命名空间中,那里。并没有真正使用过这个模块。)
【讨论】:
如果你能避免一开始就创建列表,你会更快乐。
而不是
aBigList = someListMakingFunction()
filter( lambda x:x>10, aBigList )
您可能想查看生成列表的函数。
def someListMakingGenerator( ):
for x in some source:
yield x
那么您的过滤器不会占用大量内存
def myFilter( aGenerator ):
for x in aGenerator:
if x > 10:
yield x
通过使用生成器,您不会在内存中保留太多内容。
【讨论】: