假设我有这个:
[
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5},
{"name": "Pam", "age": 7}
]
通过搜索“Pam”作为名称,我想检索相关的字典:{name:“Pam”,年龄:7}
如何做到这一点?
假设我有这个:
[
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5},
{"name": "Pam", "age": 7}
]
通过搜索“Pam”作为名称,我想检索相关的字典:{name:“Pam”,年龄:7}
如何做到这一点?
当前回答
这里是一个比较,使用遍历列表,使用过滤器+lambda或重构(如果需要或对你的情况有效)你的代码dict of dicts而不是list of dicts
import time
# Build list of dicts
list_of_dicts = list()
for i in range(100000):
list_of_dicts.append({'id': i, 'name': 'Tom'})
# Build dict of dicts
dict_of_dicts = dict()
for i in range(100000):
dict_of_dicts[i] = {'name': 'Tom'}
# Find the one with ID of 99
# 1. iterate through the list
lod_ts = time.time()
for elem in list_of_dicts:
if elem['id'] == 99999:
break
lod_tf = time.time()
lod_td = lod_tf - lod_ts
# 2. Use filter
f_ts = time.time()
x = filter(lambda k: k['id'] == 99999, list_of_dicts)
f_tf = time.time()
f_td = f_tf- f_ts
# 3. find it in dict of dicts
dod_ts = time.time()
x = dict_of_dicts[99999]
dod_tf = time.time()
dod_td = dod_tf - dod_ts
print 'List of Dictionries took: %s' % lod_td
print 'Using filter took: %s' % f_td
print 'Dict of Dicts took: %s' % dod_td
输出是这样的:
List of Dictionries took: 0.0099310874939
Using filter took: 0.0121960639954
Dict of Dicts took: 4.05311584473e-06
结论: 显然,字典是最有效的搜索方法在这种情况下,你知道,你只能通过id搜索。 有趣的是,使用过滤器是最慢的解决方案。
其他回答
你必须遍历列表中的所有元素。没有捷径!
除非在其他地方保存了一个包含指向列表项的名称的字典,但这时必须处理从列表中弹出元素的后果。
将接受的答案放在函数中,以便于重用
def get_item(collection, key, target):
return next((item for item in collection if item[key] == target), None)
也可以写成
get_item_lambda = lambda collection, key, target : next((item for item in collection if item[key] == target), None)
结果
key = "name"
target = "Pam"
print(get_item(target_list, key, target))
print(get_item_lambda(target_list, key, target))
#{'name': 'Pam', 'age': 7}
#{'name': 'Pam', 'age': 7}
如果键可能不在目标字典中,请使用dict。get和避免KeyError
def get_item(collection, key, target):
return next((item for item in collection if item.get(key, None) == target), None)
get_item_lambda = lambda collection, key, target : next((item for item in collection if item.get(key, None) == target), None)
鸭子将比列表理解或过滤器快得多。它在你的对象上建立一个索引,这样查找就不需要扫描每一个项目。
PIP安装鸭
from ducks import Dex
dicts = [
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5},
{"name": "Pam", "age": 7}
]
# Build the index
dex = Dex(dicts, {'name': str, 'age': int})
# Find matching objects
dex[{'name': 'Pam', 'age': 7}]
结果:[{'name': 'Pam', 'age': 7}]
我的第一个想法是,你可能想要考虑为这些字典创建一个字典……举个例子,如果你要多次搜索它。
然而,这可能是一个不成熟的优化。有什么问题:
def get_records(key, store=dict()):
'''Return a list of all records containing name==key from our store
'''
assert key is not None
return [d for d in store if d['name']==key]
def dsearch(lod, **kw):
return filter(lambda i: all((i[k] == v for (k, v) in kw.items())), lod)
lod=[{'a':33, 'b':'test2', 'c':'a.ing333'},
{'a':22, 'b':'ihaha', 'c':'fbgval'},
{'a':33, 'b':'TEst1', 'c':'s.ing123'},
{'a':22, 'b':'ihaha', 'c':'dfdvbfjkv'}]
list(dsearch(lod, a=22))
[{'a': 22, 'b': 'ihaha', 'c': 'fbgval'},
{'a': 22, 'b': 'ihaha', 'c': 'dfdvbfjkv'}]
list(dsearch(lod, a=22, b='ihaha'))
[{'a': 22, 'b': 'ihaha', 'c': 'fbgval'},
{'a': 22, 'b': 'ihaha', 'c': 'dfdvbfjkv'}]
list(dsearch(lod, a=22, c='fbgval'))
[{'a': 22, 'b': 'ihaha', 'c': 'fbgval'}]