我想用python脚本中的任何最快方法过滤两个列表。为此,我使用了内置的filter()
方法。但是它很慢并且花了太多时间因为我有很大的名单,我认为每个列表中的项目超过500万或者可能更多。
我不知道怎么做。如果有人有想法或写小功能请。
答案 0 :(得分:14)
也许您的列表太大而且不适合内存,并且您遇到thrashing。 如果源位于文件中,则不需要同时在内存中存储整个列表。尝试使用 itertools ,例如:
from itertools import ifilter
def is_important(s):
return len(s)>10
filtered_list = ifilter(is_important, open('mylist.txt'))
请注意, ifilter 会返回一个快速且内存效率高的迭代器。
Generator Tricks是David M. Beazley的教程,教授生成器的一些有趣用法。
答案 1 :(得分:4)
如果您可以避免首先创建列表,那么您会更开心。
而不是
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
通过使用生成器,你不会在内存中留下太多东西。
答案 2 :(得分:2)
我想filter()的速度和你可能获得的速度一样快,而不必用C编写过滤函数(在这种情况下,你最好用C编写整个过滤过程)。
为什么不粘贴要过滤的功能?这可能会导致更容易的优化。
答案 3 :(得分:2)
过滤器将创建一个新列表,因此如果您的原始文件非常大,最终可能会使用最多两倍的内存。 如果您只需要迭代地处理结果,而不是将其用作真正的随机访问列表,那么最好使用它 而是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)”)
答案 4 :(得分:1)
在使用C语言之前,您可以尝试numpy。也许你可以将过滤变成数字运算。
答案 5 :(得分:1)
知道条件列表理解通常比相应的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
命名空间中。那里没有真正使用过该模块。)