鉴于:
[
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5},
{"name": "Pam", "age": 7}
]
如何通过 name == "Pam"
进行搜索,以检索下面对应的字典?
{"name": "Pam", "age": 7}
鉴于:
[
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5},
{"name": "Pam", "age": 7}
]
如何通过 name == "Pam"
进行搜索,以检索下面对应的字典?
{"name": "Pam", "age": 7}
你可以使用一个生成器表达式:
>>> 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)
要找到列表中元素的索引而不是元素本身,可以使用enumerate()函数对列表进行枚举:
next((i for i, item in enumerate(dicts) if item["name"] == "Pam"), None)
在我看来,这是最符合Python风格的方法:
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中,返回一个过滤器对象。因此,Python 3的解决方案如下:
list(filter(lambda person: person['name'] == 'Pam', people))
len()
这样的函数,你需要先在结果上调用list()
。或者可以参考这里:https://dev59.com/LmIk5IYBdhLWcg3wiuqk。 - wasabigeeknext(filter(lambda x: x['name'] == 'Pam', dicts))
- xgMz@Frédéric Hamidi的回答很好。在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]
def search2(name, age, people):
中添加一个参数 age
,也不要忘记传递这个参数 =)。我刚刚尝试了两个条件,它可以工作! - hotenov我测试了各种方法来遍历一个字典列表并返回其中键 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
c()
比简单迭代列表 a()
要快那么多吗? - knowledge_seekerpeople = [
{'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
- Jack James您是否尝试过使用pandas包?它非常适合这种搜索任务并且已经做了优化。
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) ]
我在下面添加了一些基准测试,以说明pandas在更大规模(即10万个以上的条目)上的更快运行时间:
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
在@FrédéricHamidi的基础上,我只想稍微补充一点。
如果你不确定一个键是否在字典列表中,可以尝试以下方法:
next((item for item in dicts if item.get("name") and item["name"] == "Pam"), None)
item.get("name") == "Pam"
。该语句需要翻译成中文且不改变原意,可译为“或者简单地说,item.get("name") == "Pam"
”。 - Andreas Haferburg使用列表解析式的一种简单方法是,如果l
是列表:
l = [
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5},
{"name": "Pam", "age": 7}
]
[d['age'] for d in l if d['name']=='Tom']
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'}]
[item for item in dicts if item["name"] == "Pam"][0]
是什么意思? - Mobergenumerate()
添加到代码中以生成运行索引:next(i for i, item in enumerate(dicts) if item["name"] == "Pam")
。 - Martijn Pieters