Pythonスクリプトで最速の方法で2つのリストをフィルタリングしたい。filter()この目的のために組み込みメソッドを使用しました。しかし、リストが非常に大きいため、非常に遅く、時間がかかりすぎます。各リストに500万を超えるアイテムがあるか、それ以上になる可能性があります。どうやって作るのかわからない。誰かがアイデアを持っているか、小さな関数を書いてください。
6 に答える
リストが大きすぎてメモリに収まらず、スラッシングが発生する可能性があります。ソースがファイルにある場合、リスト全体を一度にメモリに格納する必要はありません。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 によるチュートリアルで、ジェネレータの興味深い使い方を教えています。
そもそもリストの作成を避けることができれば、もっと幸せになれるでしょう。
それよりも
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 倍のメモリを使用することになります。結果を実際のランダム アクセス リストとして使用するのではなく、結果を繰り返し処理する必要がある場合は、代わりに ifilter を使用することをお勧めします。すなわち。
for x in itertools.ifilter(condition_func, my_really_big_list):
do_something_with(x)
その他の高速化のヒントは、自分で作成した関数ではなく、python ビルトインを使用することです。チェックを無効にするためにラムダを導入する必要がある場合に特に備えて、 itertools.ifilterfalse があります。(例: "ifilter(lambda x: not x.isalpha(), l)" は "ifilterfalse(str.isalpha, l)" と記述します)
一般に、条件付きリスト内包表記は、対応するラムダよりもはるかに高速であることを知っておくと便利です。
>>> 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 わかりません。モジュールを実際にあまり使用していません。)
C で行う前に、 numpyを試すことができます。おそらく、フィルタリングを数値クランチに変えることができます。