Python检查值是否在字典列表中

11

我有一个包含字典的列表,例如:

[{'name':'Bernard','age':7},{'name':'George','age':4},{'name':'Reginald','age':6}]
我想检查一个字符串值是否与列表中任何字典的'name'值相同。例如,'Harold'将返回False,而'George'将返回True。我知道可以通过循环遍历列表中的每个项目来实现这一点,但我想知道是否有更有效的方法?

2
即使是内置函数也会循环遍历字典。 - Henrik P. Hessel
1
你为什么要以这种方式表示你的数据?为什么不创建一个名为Person的类,其中包含属性nameage,然后创建一个列表或字典来存储它们呢? - Björn Pollex
如果没有重复,非常相关:https://dev59.com/oG855IYBdhLWcg3wXC5- - tokland
如果单个项目是只读的,您可以使用Person = collections.namedtuple('Person', 'name age')代替@Space_C0wb0y建议的字典:L = [Person(**d) for d in L] - jfs
5个回答

17

如果你只有这个字典列表,那么没有更有效的方法。

但是,如果你需要频繁检查,你可以提取一个包含姓名:年龄项的字典:

l = [{'name':'Bernard','age':7},{'name':'George','age':4},{'name':'Reginald','age':6}]
d = dict((i['name'], i['age']) for i in l)

现在你有一个变量d

{'Bernard': 7, 'George': 4, 'Reginald': 6}

现在你可以进行检查:

'Harold' in d   -> False
'George' in d   -> True

使用这种方法比迭代原始列表要快得多。


7
或者更好的方法是将其提取到一个集合中。 s = set((i['name'] for i in l))。+1 - Chinmay Kanchi
目前我不需要多次使用它,但我一定会记住这个,谢谢。 - chrism
2
注意:如果你有一个字典列表,有一种更有效的方法,例如你可以按照名称排序它 L.sort(key=itemgetter('name')) 并使用 bisect 模块执行二分查找。在实践中,你可以像 @Chinmay Kanchi 建议的那样使用集合或者像 @KennyTM 的答案中使用 any() 进行线性搜索。 - jfs

15

正确的解决方案

有一种比循环更高效的方法。如果使用operators.itemgetter,则可以进行简单的if x in y检查

#to simply check if the list of dicts contains the key=>value pair
'George' in map(itemgetter('name'), list_of_dicts)

#if you want to get the index 
index = map(itemgetter('name'), list_of_dicts).index("George") if 'George' in map(itemgetter('name'), list_of_dicts) else None

8
如果您正在使用Python 3,则可以使用以下代码:list(map(itemgetter('name'), list_of_dicts)).index('George')。如果list.index()未找到任何项,则还可以将其放置在try..except ValueError中,而不是执行两个itemgetter()查找。请注意,翻译并没有改变原来的意思,并尽可能地使内容通俗易懂。 - timss

1

我觉得列表推导式在这里也可以解决问题。

names = [i['name'] for i in l]

然后像这样使用:

'Bernard' in names (True)
'Farkle' in names (False)

或者一行代码(如果只有一个检查)

'Bernard' in [i['name'] for i in l] (True)

0
l = [{'name':'Bernard','age':7},{'name':'George','age':4},{'name':'Reginald','age':6}]
search_for = 'George'
print True in map(lambda person: True if person['name'].lower() == search_for.lower() else False, l )

这不是一个很好的解决方案。KennyTM提出了一个更简单的解决方案,使用了“any”,但出于某种原因他选择将其删除。 - Björn Pollex
@BjörnPollex,你能在这里复现一下答案吗? - James Draper

0
smf = [{'name':'Bernard','age':7},{'name':'George','age':4},{'name':'Reginald','age':6}]
def names(d):
    for i in d:
        for key, value in i.iteritems():
             if key == 'name':
                 yield value


In [5]: 'Bernard' in names(smf)
Out[5]: True


In [6]: 'Bernardadf' in names(smf)
Out[6]: False

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接