假设我有这个:

[
  {"name": "Tom", "age": 10},
  {"name": "Mark", "age": 5},
  {"name": "Pam", "age": 7}
]

通过搜索“Pam”作为名称,我想检索相关的字典:{name:“Pam”,年龄:7}

如何做到这一点?


当前回答

我测试了各种方法来遍历字典列表并返回键x具有特定值的字典。

结果:

速度:列表推导>生成器表达式>>常规列表迭代>>>过滤器。 所有的比例都与列表中的字典数量线性(10x列表大小-> 10x时间)。 对于大量(数千个)键,每个字典的键不会显著影响速度。请看我计算的图表:https://imgur.com/a/quQzv(方法名称见下文)。

所有测试均使用Python 3.6.4, W7x64完成。

from random import randint
from timeit import timeit


list_dicts = []
for _ in range(1000):     # number of dicts in the list
    dict_tmp = {}
    for i in range(10):   # number of keys for each dict
        dict_tmp[f"key{i}"] = randint(0,50)
    list_dicts.append( dict_tmp )



def a():
    # normal iteration over all elements
    for dict_ in list_dicts:
        if dict_["key3"] == 20:
            pass

def b():
    # use 'generator'
    for dict_ in (x for x in list_dicts if x["key3"] == 20):
        pass

def c():
    # use 'list'
    for dict_ in [x for x in list_dicts if x["key3"] == 20]:
        pass

def d():
    # use 'filter'
    for dict_ in filter(lambda x: x['key3'] == 20, list_dicts):
        pass

结果:

1.7303 # normal list iteration 
1.3849 # generator expression 
1.3158 # list comprehension 
7.7848 # filter

其他回答

将接受的答案放在函数中,以便于重用

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)
names = [{'name':'Tom', 'age': 10}, {'name': 'Mark', 'age': 5}, {'name': 'Pam', 'age': 7}]
resultlist = [d    for d in names     if d.get('name', '') == 'Pam']
first_result = resultlist[0]

这是一种方法……

你可以使用列表推导式:

def search(name, people):
    return [element for element in people if element['name'] == name]
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'}]

你必须遍历列表中的所有元素。没有捷径!

除非在其他地方保存了一个包含指向列表项的名称的字典,但这时必须处理从列表中弹出元素的后果。