2017-07-10 10 views
3

私は2つの辞書のリストを持っています。Pythonで辞書の2つのリストの間で共通の要素を検索する最速の方法

list1 = [{'user_id':23, 'user_name':'John', 'age':30}, 
     {'user_id':24, 'user_name':'Shaun', 'age':31}, 
     {'user_id':25, 'user_name':'Johny', 'age':32}] 

list2 =[{'user_id':23}, 
     {'user_id':25}] 

は今、私は私のlist1は、数百万行が含まれている可能性があるため、出力

list3 = [{'user_id':23, 'user_name':'John', 'age':30}, 
     {'user_id':25, 'user_name':'Johny','age':32}] 

は、私が最も効率的な方法を望んで欲しいです。

+1

十分速くないものを試しましたか? – Ryan

+0

[this](https://stackoverflow.com/questions/382466/comparing-massive-lists-of-dictionaries-in-python)または[this](https:// stackoverflow。com/questions/9845369/comparison-2-lists-consisting-of-unique-keys-in-python)を使用しています。彼らは十分に速くなかったのですか?これを実装しようとしましたが、パフォーマンスの問題がありましたか? – idjaw

+1

'list1'のスキャンを1回だけ行う必要がある場合は、Jean-FrançoisFabreの戦略を使用する必要があります。しかし、複数回検索する必要がある場合は、omri_saadonの回答に従って、リストをdictに変換することを真剣に検討する必要があります。この新しいdictの内部アイテムにdictsを使用するのではなく、タプルまたは名前付きタプルを使用した場合はRAMを節約します。 –

答えて

5

list2をすばやく変換する必要があります。私はその後、フィルタされたリストの内包表記を使用してlist3を構築set

それのうち
list1 = [{'user_id':23, 'user_name':'John','age':30}, 
     {'user_id':24, 'user_name':'Shaun','age':31}, 
     {'user_id':25, 'user_name':'Johny','age':32}] 

list2 =[{'user_id':23}, 
     {'user_id':25}] 

list2_ids = {d['user_id'] for d in list2} 

作ると思います。それはsetなく線形検索からの参照を使用しているため、その場合にはin list2_idsは非常に高速です:

list3 = [x for x in list1 if x['user_id'] in list2_ids] 

print(list3) 

結果:

[{'user_id': 23, 'user_name': 'John', 'age': 30}, {'user_id': 25, 'user_name': 'Johny', 'age': 32}] 
1

キーがuser_idとあるとき私は辞書にあなたのlist1を変換するでしょう値はnameageです。

dictに多くの要素が含まれていても、このdictを参照すると、複雑さはO(1)となります。その場合

、すべてのユーザーIDを見つけることの全体の複雑さは、あなたが一緒にDATAFRAMEするマージするパンダを使用することができますO(len(list2))

dict1 = {23 : {'user_name':'John', 'age':30}, 
     24 : {'user_name':'Shaun', 'age':31}, 
     25 : {'user_name':'Johny', 'age':32}} 

list2 =[{'user_id':23}, 
     {'user_id':25}] 

res = [dict1.get(user['user_id']) for user in list2 if user['user_id'] in dict1] 

print (res) 

>>> [{'user_name': 'John', 'age': 30}, {'user_name': 'Johny', 'age': 32}] 
+0

私の 'list1'をもう一度変換するには、' list1'の権利全体を反復する必要があります。それ自体は複雑さを増します。 – curiousguy

+0

@curiousguy、一度やります。このデータ構造の後に、O(1)の複雑さで多くの検索を適用することができます。 –

+0

はい私はあなたに同意します、そのフォーマットでの検索は非常に高速です。 probは私の 'list1'で、' list2'は入力に基づいて変化し続けます。それゆえ、私は毎回それをしなければなりません。 – curiousguy

0

です。以前のポスターのように「USER_ID」に
2.マージ2つのデータフレーム

import pandas as pd 
list1 = [{'user_id':23, 'user_name':'John', 'age':30}, 
      {'user_id':24, 'user_name':'Shaun', 'age':31}, 
      {'user_id':25, 'user_name':'Johny', 'age':32}] 
list2 =[{'user_id':23}, 
     {'user_id':25}] 
df1 = pd.DataFrame(list1) 
df1 
    age user_id user_name 
0 30  23  John 
1 31  24  Shaun 
2 32  25  Johny 
df2 = pd.DataFrame(list2) 
df2 
    user_id 
0  23 
1  25 

pd.merge(df2,df1,on='user_id') 
    user_id age user_name 
0  23 30  John 
1  25 32  Johny 
+0

実際、私はここでパンダを避けています。 – curiousguy

0

をDATAFRAMEする
1.変換の辞書を使用すると、リスト2からIDのリストを作成する必要があると述べた。

list2_ids = {d['user_id'] for d in list2} 

これを実行した後、フィルタ機能を使用することもできます。

filter(lambda x: x['user_id'] in list2_ids, list1) 

T彼は最適化されていませんが、並列計算のための複数の実装を持つ利点があります(大量のデータを扱う場合には必要になるかもしれません)。最善の解決策は、性能面、おそらく設定されている交差点(comparison)言われていること

:あなたが確信している場合はリストは重複を含まない

unique_ids = set([d['user_id'] for d in list1]) & set([d['user_id'] for d in list2]) 
list3 = [x for x in list1 if x['user_id'] in unique_ids] 

あなたがを無視することができますがを設定します。

関連する問題