2017-11-13 7 views
0

ここではPythonのリストについていくつかの記事を見てきましたが、私の質問に正解は見つかりません。それはコードを最適化するためです。Pythonの "inner join"リストのコードが遅い

私は2つのリストを比較するためのPythonコードを持っています。同じコードを見つけて、2番目の位置の値を変更する必要があります。最終的には完璧に動作しますが、時間がかかります。 SQLでは、このクエリは2分を要しません....しかし、ここでは15分を費やしています。だから、メモリの問題か悪いコードの問題か分かりません。

私は2つのリストを持っています。 最初の[code、points]です。 2番目の[コード、ライセンス] 最初のリストの最初の値(コード)が2番目のリスト(コード)の最初の値と一致する場合、それは、例えば、ライセンスが「これ」に等しい場合、最初のリスト(点)の第2の値を更新しなければならない:

itemswithscore = [5675, 0], [6676, 0], [9898, 0], [4545, 0] 
itemswithlicense = [9999, 'ATR'], [9191, 'OPOP'], [9898, 'THIS'], [2222, 'PLPL'] 

for sublist1 in itemswithscore: 
    for sublist2 in itemswithlicense: 
     if sublist1[0] == sublist2[0]: #this is the "inner join" :) 
      if sublist2[1] == 'THIS': #It has to be license 'THIS' 
       sublist1[1] += 50 #I add 50 to the score value 

最後に、私は、コード9868で更新リストを持っている:

itemswithscore = [5675, 0], [6676, 0], [9898, 50], [4545, 0] 
事前に

二つのリストが80.000値の誰もが持っていることは事実である。.. :(

感謝!!!

答えて

4

私はdictsとして/ /変換にあなたのデータ構造を維持することをお勧めします。それには方法、あなたはループの入れ子になったで両方のリストを反復処理する必要はありません - O(N )またはO(n×mの)操作 - リストのコード番号は、スコア値を更新する前に揃えどこを探して。

あなたは、単に対応する辞書のキーは検索文字列と一致するスコアの値が更新されます:あなたはパンダを使用することができればそれは非常に効率的である

dct_score = dict(itemswithscore) 
dct_license = dict(itemswithlicense) 
for k in dct_score: 
    if dct_license.get(k) == 'THIS': # use dict.get in case key does not exist 
     dct_score[k] += 50 
+0

素晴らしい!それは完璧で非常に速く動作します。私はそれが最善の解決策であると確信しています。 しかし、私は質問があります。あなたが言うとき:dct_scoreのkのための : もしdct_licenseなら。get(k)== 'これ' 'THIS'という値がキーや辞書の値に現れることがありますか? つまり、リストのような固定位置を指定することはできません。例えば、 itemswithscoreのサブリスト:sublist [1] –

+0

その他の質問: 私は非常に大きなリスト(キー、値)を扱っています。 そして、私は、異なるクエリに応じて(リストの「値」部分に)多かれ少なかれスコアを与えるために多くのクエリを渡します。 リストの代わりに辞書を使用する方が良いでしょうか?リストでは、値 "列"を更新する方が簡単だと分かります。 itemswithscoreのサブリスト: sublist [1] + = 50ポイント –

+1

dictsを使用する方が良いかもしれません。 'dct_scoreのkに対して:dct_score [k] + = 50' –

0

を。

だから、次の2つのデータフレームを作成し、このことができます。この

itemswithscore = [5675, 0], [6676, 0], [9898, 0], [4545, 0] 
itemswithlicense = [9999, 'ATR'], [9191, 'OPOP'], [9898, 'THIS'], [2222, 'PLPL'] 

df1 = pd.DataFrame(list(itemswithscore), columns =['code', 'points']) 
df2 = pd.DataFrame(list(itemswithlicence), columns=['code', 'license']) 

df3 = pd.merge(df1, df2 , on='code', how='inner') 
df3 = df3.drop('points', axis=1) 

希望のような単一の列に

何かをそれらをマージすることができ、もし

正しい乾杯を受け入れます!

0

私は、遅さが主にループ自体に起因すると確信していますが、これはPythonではあまり速くはありません。あなたはそうのように、変数をキャッシュすることで、多少のコード​​をスピードアップすることができます。

for sublist1 in itemswithscore: 
    a = sublist1[0] # Save to variable to avoid repeated list-lookup 
    for sublist2 in itemswithlicense: 
     if a == sublist2[0]: 
      if sublist2[1] == 'THIS': 
       sublist1[1] += 50 

をまた、あなたは'THIS'度もitemswithlicense以上では発生しないことを知ることが起こる場合は、sublist1[1]を更新した後、あなたがbreakを挿入する必要があります。

この違いがどれくらいあるか教えてください。

+0

本当に真実ではありません。 – danny

+0

@danny真実はなんですか? –

+1

上記の文全体。 Pythonのインデックス付きリストgetは常に 'O(1)'です。変数を使用するかどうかはこれを変更しません。はい、ルックアップを保存します。複雑さは関係なく変化します。上記のコードは、同じ複雑さです。 – danny