2011-08-16 83 views
29

根據dict中的某個值,我需要能夠找到list(本例中的某個項目爲dict)中的項目。在list我需要處理的結構是這樣的:Python:根據字典中的內容從列表中獲取字典

[ 
    { 
     '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' 
    } 
] 

注意事項:titlevalue可以是任何值(與相同),id將是獨一無二的。

我需要能夠從此list得到一個dict根據一個獨特的id。我知道這可以通過使用循環來完成,但這看起來很麻煩,而且我有一種感覺,有一種明顯的方法可以做到這一點,因爲我不會感謝大腦融化。

回答

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

這遍歷整個列表,直到找到匹配my_unique_id的第一個項目,然後停止。它不會在內存中存儲任何中間列表(通過使用生成器表達式)或需要顯式循環。它將my_item設置爲None未找到任何對象。這是大致相同,當循環不是由break聲明結束了被用在for循環

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

else條款。

+1

@agf你有什麼建議當有多個匹配,你想提取他們在列表(匹配的字典)? – Augiwan

+1

@UGS如果你需要掃描整個列表並建立一個結果列表,而不僅僅是找到第一個匹配,你不可能比列表理解更好,比如'[item for item in my_list if 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

這不是一個可能是非唯一ID的問題 - 這是平均'len(my_list)'比較或'len(my_list)// 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'}