迭代字典列表时避免KeyError

时间:2017-05-19 12:28:04

标签: python dictionary list-comprehension

我有一个词典列表:

test = [{'first': '1'}, {'second': '2'}, {'first': '0'}, {'third': '3'}, {'fourth': '4'}]

但是当我这样做时:

stuff = [L['first'] for L in test]
print(stuff)

我明白了:

Traceback (most recent call last):
  File "C:/Users/User/Desktop/test_run.py", line 4, in <module>
    stuff = [L['first'] for L in test]
  File "C:/Users/User/Desktop/test_run.py", line 4, in <listcomp>
    stuff = [L['first'] for L in test]
KeyError: 'first'

我知道我可能会犯一个愚蠢的错误,但有任何帮助吗?

4 个答案:

答案 0 :(得分:6)

列表理解+ if

如果你想要所有的值,你需要先检查dict是否有相应的键:

>>> [d['first'] for d in test if 'first' in d]
['1', '0']
>>> [d['sixth'] for d in test if 'sixth' in d]
[]

只有一个值

您可以使用next获取与'first'第一次出现相对应的值,如果您确定他们至少有一个带有'first'的词典值:

>>> test = [{'first': '1'}, {'second': '2'}, {'first': '0'}, {'third': '3'}, {'fourth': '4'}]
>>> next(d['first'] for d in test if 'first' in d)
'1'

否则会引发StopIteration

>>> next(d['sixth'] for d in test if 'sixth' in d)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

替代数据格式

最后,如果经常进行此操作,稍微更改格式可能会很有趣:

from collections import defaultdict
data = defaultdict(list)

test = [{'first': '1'}, {'second': '2'}, {'first': '0'}, {'third': '3'}, {'fourth': '4'}]

for d in test:
    for k in d:
        data[k].append(d[k])

print(data)
# defaultdict(<type 'list'>, {'second': ['2'], 'fourth': ['4'], 'third': ['3'], 'first': ['1', '0']})
print(data['first'])
# ['1', '0']
print(data['sixth'])
# []

for循环只需要一次,之后查找非常快。

答案 1 :(得分:1)

这可以通过理解来解决,但我个人只是简单地使用for循环 - 主要是因为它不会需要 if条件。作为功​​能包装它也可以很容易地重复使用(即用于其他键):

def get_key(list_of_dicts, key):
    for dct in test:
        try:
            yield dct[key]
        except KeyError:
            pass

这是一个生成器,因此您可以将其强制转换为列表,或者在迭代它的任何地方使用它:

>>> list(get_key(test, 'first'))
['1', '0']

答案 2 :(得分:1)

&#39;测试&#39;是一个带有可变键的字典列表。假设你只想要词典中带有关键词&#39;第一个&#39;以列表形式返回。我们可以做到,

test = [{'first': '1'}, {'second': '2'}, {'first': '0'}, {'third': '3'}, {'fourth': '4'}]
stuff = [y['first'] for y in filter(lambda x: 'first' in x, test)]

1)过滤功能只返回带有键的列表词典&#39;首先&#39;
  2)使用该列表,我们可以应用列表推导来获取词典中的值列表(使用键&#39; first&#39;)。

希望这有帮助。

答案 3 :(得分:0)

L正在迭代测试元素。当L到达{'second': '2'} L['first']时会抛出一个关键错误。

解决方法是

[L.get('first') for L in test]

当密钥不存在时,通过get方法访问字典元素不会引发异常。相反,它将返回默认值。

如果找不到密钥,您也可以传递自定义的默认值:

[L.get('first','not_found') for L in test]

如果你想避免返回一个默认值,那么你必须在列表理解中引入一个条件:

[L['first'] for L in test if 'first' in test]