Answers:
您可以使用生成器表达式:
>>> dicts = [
...     { "name": "Tom", "age": 10 },
...     { "name": "Mark", "age": 5 },
...     { "name": "Pam", "age": 7 },
...     { "name": "Dick", "age": 12 }
... ]
>>> next(item for item in dicts if item["name"] == "Pam")
{'age': 7, 'name': 'Pam'}
如果您需要处理不存在的项目,则可以执行用户Matt 在其注释中建议的操作,并使用略有不同的API提供默认值:
next((item for item in dicts if item["name"] == "Pam"), None)
为了找到项目的索引,而不是项目本身,可以枚举()列表:
next((i for i, item in enumerate(dicts) if item["name"] == "Pam"), None)
              [item for item in dicts if item["name"] == "Pam"][0]呢
                    enumerate()以生成运行索引:next(i for i, item in enumerate(dicts) if item["name"] == "Pam")。
                    在我看来,这是最蟒蛇的方式:
people = [
{'name': "Tom", 'age': 10},
{'name': "Mark", 'age': 5},
{'name': "Pam", 'age': 7}
]
filter(lambda person: person['name'] == 'Pam', people)
结果(在Python 2中作为列表返回):
[{'age': 7, 'name': 'Pam'}]
注意:在Python 3中,将返回一个过滤器对象。因此,python3解决方案将是:
list(filter(lambda person: person['name'] == 'Pam', people))
              r是list
                    next(filter(lambda x: x['name'] == 'Pam', dicts))
                    @FrédéricHamidi的回答很好。在Python 3.x中,语法.next()略有变化。因此稍作修改:
>>> dicts = [
     { "name": "Tom", "age": 10 },
     { "name": "Mark", "age": 5 },
     { "name": "Pam", "age": 7 },
     { "name": "Dick", "age": 12 }
 ]
>>> next(item for item in dicts if item["name"] == "Pam")
{'age': 7, 'name': 'Pam'}
如@Matt的评论中所述,您可以这样添加默认值:
>>> next((item for item in dicts if item["name"] == "Pam"), False)
{'name': 'Pam', 'age': 7}
>>> next((item for item in dicts if item["name"] == "Sam"), False)
False
>>>
              您可以使用列表推导:
def search(name, people):
    return [element for element in people if element['name'] == name]
              people = [
{'name': "Tom", 'age': 10},
{'name': "Mark", 'age': 5},
{'name': "Pam", 'age': 7}
]
def search(name):
    for p in people:
        if p['name'] == name:
            return p
search("Pam")
              def search(list, key, value):     for item in list:         if item[key] == value:             return item
                    我测试了各种方法来浏览字典列表,然后返回键x具有特定值的字典。
结果:
所有测试均使用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
              向@FrédéricHamidi添加一点点。
如果您不确定某个键是否在字典列表中,可以使用以下方法:
next((item for item in dicts if item.get("name") and item["name"] == "Pam"), None)
              item.get("name") == "Pam"
                    您是否尝试过熊猫包装?它非常适合此类搜索任务,并且也进行了优化。
import pandas as pd
listOfDicts = [
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5},
{"name": "Pam", "age": 7}
]
# Create a data frame, keys are used as column headers.
# Dict items with the same key are entered into the same respective column.
df = pd.DataFrame(listOfDicts)
# The pandas dataframe allows you to pick out specific values like so:
df2 = df[ (df['name'] == 'Pam') & (df['age'] == 7) ]
# Alternate syntax, same thing
df2 = df[ (df.name == 'Pam') & (df.age == 7) ]
我在下面添加了一些基准测试,以大范围地(即100k +项)说明熊猫的运行时间:
setup_large = 'dicts = [];\
[dicts.extend(({ "name": "Tom", "age": 10 },{ "name": "Mark", "age": 5 },\
{ "name": "Pam", "age": 7 },{ "name": "Dick", "age": 12 })) for _ in range(25000)];\
from operator import itemgetter;import pandas as pd;\
df = pd.DataFrame(dicts);'
setup_small = 'dicts = [];\
dicts.extend(({ "name": "Tom", "age": 10 },{ "name": "Mark", "age": 5 },\
{ "name": "Pam", "age": 7 },{ "name": "Dick", "age": 12 }));\
from operator import itemgetter;import pandas as pd;\
df = pd.DataFrame(dicts);'
method1 = '[item for item in dicts if item["name"] == "Pam"]'
method2 = 'df[df["name"] == "Pam"]'
import timeit
t = timeit.Timer(method1, setup_small)
print('Small Method LC: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup_small)
print('Small Method Pandas: ' + str(t.timeit(100)))
t = timeit.Timer(method1, setup_large)
print('Large Method LC: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup_large)
print('Large Method Pandas: ' + str(t.timeit(100)))
#Small Method LC: 0.000191926956177
#Small Method Pandas: 0.044392824173
#Large Method LC: 1.98827004433
#Large Method Pandas: 0.324505090714
              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]
这是一种方法
您可以通过在Python中使用filter和next方法来实现。
filter方法过滤给定的序列并返回一个迭代器。
next方法接受迭代器,并返回列表中的下一个元素。
因此,您可以通过以下方式找到元素
my_dict = [
    {"name": "Tom", "age": 10},
    {"name": "Mark", "age": 5},
    {"name": "Pam", "age": 7}
]
next(filter(lambda obj: obj.get('name') == 'Pam', my_dict), None)
输出是
{'name': 'Pam', 'age': 7}
注意:None如果找不到我们正在搜索的名称,上述代码将返回以防万一。
我的第一个想法是,您可能要考虑创建一个包含这些词典的字典...例如,如果您要搜索的词典次数不止一次。
但是,这可能是过早的优化。有什么问题:
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]
              您可以尝试以下方法:
''' lst: list of dictionaries '''
lst = [{"name": "Tom", "age": 10}, {"name": "Mark", "age": 5}, {"name": "Pam", "age": 7}]
search = raw_input("What name: ") #Input name that needs to be searched (say 'Pam')
print [ lst[i] for i in range(len(lst)) if(lst[i]["name"]==search) ][0] #Output
>>> {'age': 7, 'name': 'Pam'} 
              这是一个使用迭代遍历列表的比较,使用filter + lambda或重构(如果需要或对您的情况有效)的代码将您的代码用于命令,而不是命令列表
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 find_dict_in_list(dicts, default=None, **kwargs):
    """Find first matching :obj:`dict` in :obj:`list`.
    :param list dicts: List of dictionaries.
    :param dict default: Optional. Default dictionary to return.
        Defaults to `None`.
    :param **kwargs: `key=value` pairs to match in :obj:`dict`.
    :returns: First matching :obj:`dict` from `dicts`.
    :rtype: dict
    """
    rval = default
    for d in dicts:
        is_found = False
        # Search for keys in dict.
        for k, v in kwargs.items():
            if d.get(k, None) == v:
                is_found = True
            else:
                is_found = False
                break
        if is_found:
            rval = d
            break
    return rval
if __name__ == '__main__':
    # Tests
    dicts = []
    keys = 'spam eggs shrubbery knight'.split()
    start = 0
    for _ in range(4):
        dct = {k: v for k, v in zip(keys, range(start, start+4))}
        dicts.append(dct)
        start += 4
    # Find each dict based on 'spam' key only.  
    for x in range(len(dicts)):
        spam = x*4
        assert find_dict_in_list(dicts, spam=spam) == dicts[x]
    # Find each dict based on 'spam' and 'shrubbery' keys.
    for x in range(len(dicts)):
        spam = x*4
        assert find_dict_in_list(dicts, spam=spam, shrubbery=spam+2) == dicts[x]
    # Search for one correct key, one incorrect key:
    for x in range(len(dicts)):
        spam = x*4
        assert find_dict_in_list(dicts, spam=spam, shrubbery=spam+1) is None
    # Search for non-existent dict.
    for x in range(len(dicts)):
        spam = x+100
        assert find_dict_in_list(dicts, spam=spam) is None
              这里提出的大多数(如果不是全部)实现都有两个缺陷:
更新的主张:
def find_first_in_list(objects, **kwargs):
    return next((obj for obj in objects if
                 len(set(obj.keys()).intersection(kwargs.keys())) > 0 and
                 all([obj[k] == v for k, v in kwargs.items() if k in obj.keys()])),
                None)
也许不是最Python的,但至少具有更多的故障保护功能。
用法:
>>> obj1 = find_first_in_list(list_of_dict, name='Pam', age=7)
>>> obj2 = find_first_in_list(list_of_dict, name='Pam', age=27)
>>> obj3 = find_first_in_list(list_of_dict, name='Pam', address='nowhere')
>>> 
>>> print(obj1, obj2, obj3)
{"name": "Pam", "age": 7}, None, {"name": "Pam", "age": 7}
该要点。