2017-05-11 3 views
2

私は文字列のリストを持っています。私は文字 '&'で始まり、それらを別のリストに格納するリスト内のすべてのアイテムを取得したいと思いました。それぞれのアイテムをループしてみましたが、特にリストの長さが非常に長い場合は遅いことがわかりました。それを行うための他の方法はありますか?各項目をループする以外の特定の文字で始まる項目を見つけるより良い方法はありますか?

ここは私がやったことです。読書のための

myList=['& apple','^ banana','& pineapple'] 
newList=[] 

for v in myList: 
    if v.startswith('&'): 
     newList.append(v) 

おかげで...

+1

を取得します。 – bhansa

+0

len(myList)== 10 ** 9 .. –

+1

ここでは、yieldとappendの使用の利点を見ることができます。http://stackoverflow.com/questions/3487802/which-is-generally-faster-a-yield- or-an-append –

答えて

4

必ずしも速くない短い方法はあり:リスト内包が。あなたは、データ処理の多くを行っている場合

myList = ['& apple','^ banana','& pineapple'] 
newList = [v for v in myList if v.startswith('&')] 

、パンダが速くなることがあります。これは遅すぎる

import pandas 
df = pandas.DataFrame({'myList': myList}) 
newList = df[df.myList.str.startswith('&')] 

最後に、あなたが最初に構築している間、分類を行うために有用である可能性がありますリスト。非常に大きい場合は、おそらくファイルから読み込んだり計算したりしているので、そのループにnewListを作ることができます。

+1

これは完璧な答えの例です。ちょうどいい、共有のためのおかげで:) –

+1

収穫は少し速いですか?私はおそらく... –

+1

ジェネレータを使用しても、すべての要素を反復処理する必要はありません。したがって、ジェネレータをいくつか使用し、それらを繰り返し処理する場合は、繰り返しの時間を節約できるため、3つのリスト内包表記を使用するよりも速くなりますが、ジェネレータを反復することはリストを反復するよりも高速ではありません。 – chthonicdaemon

2

あなたはこのような、新しいリストに追加する代わりにそれをもたらすことができます:何があると仮定しない

mygenerator = generates() 
    for i in mygenerator: 
    #do something 
2

:あなたは同じように、発電機で物事を行うことができます

myList=['& apple','^ banana','& pineapple'] 

def generates(): 
    for v in myList: 
     if v.startswith('&'): 
      yield v 

文字列の一重引用符( ')...

from re import findall 

myList=['& apple','^ banana','& pineapple'] 

newList=findall(r'&[^\']*',str(myList)) 
3

解決策を提案し、自分の投稿を追加しますh、赤面が赤くなり、残りの部分を軽く叩く。このテストスクリプトは、最も遅くなるように整理されています。私は50%一致するリストを使用します。オリジナルのケースとイールドケースでは、一致率が高いほどパフォーマンスが悪くなります。私のジャンキーのラップトップ上

from timeit import timeit 

# generate test with half matching 
myList = ['&abc', 'def'] * 10000 

def orig(): 
    newList = [] 
    for v in myList: 
     if v.startswith('&'): 
      newList.append(v) 

print('orig') 
print(timeit("orig()", setup="from __main__ import orig", number=5000)) 

def doyield(): 
    def inner(myList): 
     for v in myList: 
      if v.startswith('&'): 
       yield v 
    newList = list(inner(myList)) 

print('yield') 
print(timeit("doyield()", setup="from __main__ import doyield", number=5000)) 

def comp1(): 
    newList = [v for v in myList if v.startswith('&')] 

print('comprehension with startswith') 
print(timeit("comp1()", setup="from __main__ import comp1", number=5000)) 

def comp2(): 
    newList = [v for v in myList if v and v[0]=='&'] 

print('comprehension with compare') 
print(timeit("comp2()", setup="from __main__ import comp2", number=5000)) 

orig 
55.8570241928 
yield 
50.6004090309 
comprehension with startswith 
47.4232199192 
comprehension with compare 
24.5065619946 

UPDATE

問題でcythonコンパイラを投げると何が起こるか見てみましょう。注:cythonをインストールする必要があります。パッケージ化されているシステムでは簡単です。それ以外の場合は、チェックアウトhttp://cython.orgです。私はテストを別のモジュールに分割し、新しいテストモジュールにインポート時にコンパイルするようにしました。 cythonモジュールをコンパイルする他の方法があります(cython Webサイトのsetup.py情報を参照してください)。しかし、この方法はこのテストには簡単です。欠点は、最初の実行時にコードがコンパイルされることです(しばらく待つ必要があります)、エラーが発生する可能性があります。

興味深いことに、元のコードははるかに優れていますが、4番目のコードはこれまでのところ最速です。

test.py

from timeit import timeit 

# generate test with half matching 
myList = ['&abc', 'def'] * 10000 

def orig(): 
    newList = [] 
    for v in myList: 
     if v.startswith('&'): 
      newList.append(v) 

def doyield(): 
    def inner(myList): 
     for v in myList: 
      if v.startswith('&'): 
       yield v 
    newList = list(inner(myList)) 

def comp1(): 
    newList = [v for v in myList if v.startswith('&')] 

def comp2(): 
    newList = [v for v in myList if v and v[0]=='&'] 

cytest。それを実行しているPY

import pyximport 
pyximport.install(pyimport = True) 
from test2 import * 
from timeit import timeit 


print('orig') 
print(timeit("orig()", setup="from __main__ import orig", number=5000)) 

print('yield') 
print(timeit("doyield()", setup="from __main__ import doyield", number=5000)) 

print('comprehension with startswith') 
print(timeit("comp1()", setup="from __main__ import comp1", number=5000)) 

print('comprehension with compare') 
print(timeit("comp2()", setup="from __main__ import comp2", number=5000)) 

私はまた、制約を提供してください、これが遅いどの

orig 
29.2698290348 
yield 
31.7977068424 
comprehension with startswith 
29.41690588 
comprehension with compare 
4.69118189812 
関連する問題