2011-08-16 6 views
29

の中の何らかの値に基づいてlist(ここではアイテムはdict)のアイテムを見つける必要があります。Python:dict内の何かを基にしたリストから辞書を取得

[ 
    { 
     'title': 'some value', 
     'value': 123.4, 
     'id': 'an id' 
    }, 
    { 
     'title': 'another title', 
     'value': 567.8, 
     'id': 'another id' 
    }, 
    { 
     'title': 'last title', 
     'value': 901.2, 
     'id': 'yet another id' 
    } 
] 

警告:私はプロセスに必要listの構造は次のようになりますtitlevalueは、任意の値(と同じ)することができ、idはユニークになります。

このlistからユニークなidに基づいてdictを取得する必要があります。私はこれがループを使って行うことができることを知っていますが、これは扱いにくいようであり、私は脳の融解のおかげでこれを見ていないという明らかな方法があるという気持ちがあります。

答えて

54
my_item = next((item for item in my_list if item['id'] == my_unique_id), None) 

my_unique_idに一致する最初の項目が見つかるまでリストを介して、この反復処理は、その後停止します。メモリにジェネレータ式を使用して中間リストを格納したり、明示的なループを必要とすることはありません。オブジェクトなしのmy_itemNoneが設定されています。これは、約ループがbreak文で終了していないときforループ上の

for item in my_list: 
    if item['id'] == my_unique_id: 
     my_item = item 
     break 
else: 
    my_item = None 

else句が使用されているのと同じです。

+1

@agf複数の一致があり、それらを(一致するdictsの)リストで抽出したい場合は、どのようなことをお勧めしますか? – Augiwan

+1

@UGSリスト全体をスキャンして結果リストを構築し、最初のマッチを見つけるだけでなく、 '[item '[id' ] == my_unique_id] '。 – agf

0
In [2]: test_list 
Out[2]: 
[{'id': 'an id', 'title': 'some value', 'value': 123.40000000000001}, 
{'id': 'another id', 'title': 'another title', 'value': 567.79999999999995}, 
{'id': 'yet another id', 'title': 'last title', 'value': 901.20000000000005}] 

In [3]: [d for d in test_list if d["id"] == "an id"] 
Out[3]: [{'id': 'an id', 'title': 'some value', 'value': 123.40000000000001}] 

使用リスト内包

+0

これは、一致が見つかった後でもリストを通過し続けます。 – agf

+0

IDが一意でなければならない場合は、これでlen()を実行すると、一意でないIDが表示されていることが表示されます – TyrantWave

+0

idsがユニークでない可能性はありません。 'len(my_list)'の比較や 'len(my_list)// 2'の比較です。あなたのバージョンは、必要に応じて(平均して)2倍の作業をします。 – agf

15

あなたは、この複数回行う必要がある場合、あなたはあなたのリストにIDによってインデックスさdictionnaryを再作成する必要があります。

keys = [item['id'] for item in initial_list] 
new_dict = dict(zip(keys, initial_list)) 

>>>{ 
    'yet another id': {'id': 'yet another id', 'value': 901.20000000000005, 'title': 'last title'}, 
    'an id': {'id': 'an id', 'value': 123.40000000000001, 'title': 'some value'}, 
    'another id': {'id': 'another id', 'value': 567.79999999999995, 'title': 'another title'} 
} 

またはワンライナーの仕方などで

agf:

new_dict = dict((item['id'], item) for item in initial_list) 
+2

'new_dict = dict(item_ [id ']、item)for initial_listの項目)' ...なぜ中間リストを作成してから 'zip'するのですか? – agf

0

この目的のために単純な関数を作成することができます:

lVals = [{'title': 'some value', 'value': 123.4,'id': 'an id'}, 
{'title': 'another title', 'value': 567.8,'id': 'another id'}, 
{'title': 'last title', 'value': 901.2, 'id': 'yet another id'}] 

def get_by_id(vals, expId): return next(x for x in vals if x['id'] == expId) 

get_by_id(lVals, 'an id') 
>>> {'value': 123.4, 'title': 'some value', 'id': 'an id'} 
関連する問題