2011-08-16 49 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'}