过滤Python生成器表达式

时间:2016-06-12 09:14:27

标签: python dictionary keyerror

我有一个字典dct,我希望它的每个值都可以求和,只要它们在指定的列表lst中存在相应的键。

我目前使用的代码是:

sum(dct[k] for k in lst)

在上面的生成器表达式中,我想处理KeyError,以防在列表中找不到列表中的键。我似乎无法在此生成器表达式中找到如何实现(语法方式)try - except方法或if - else方法。

如果在词典中找不到列表中的键,那么它应该继续获取其他值总和的最终结果不应受任何缺失键的影响。如果没有密钥存在,那么零应该是和的结果。

5 个答案:

答案 0 :(得分:5)

您有两种选择:

检查密钥是否存在

sum(dct[k] for k in lst if k in dct)

或使用get

sum(dct.get(k, 0) for k in lst)

如果dct.get(k, 0)dct[k]中的关键字,则k会返回dct,如果不是,则会0

答案 1 :(得分:2)

您可以简单地使用.get()尝试从字典中获取密钥的值,如果找不到,将返回None,或者您提供的默认参数为0案件。

>>> dct = {1:2, 3:4, 5:6}
>>> lst = [1,5]
>>> sum(dct.get(k, 0) for k in lst)
8    

如果某些键(或所有)不存在,则总和仍将正常运行。

>>> lst = [10, 11]
>>> sum(dct.get(k, 0) for k in lst)
0

答案 2 :(得分:1)

sum(dct[k] for k in lst if k in dct)

答案 3 :(得分:1)

您可以使用get - 词典方法,在未找到时提供默认值:

sum(dct.get(k, 0) for k in lst)

答案 4 :(得分:1)

嗯,选项很少,首选是使用dict.get()

# 1
sum(dct.get(k, 0) for k in lst)
# 2
sum(dct[k] for k in lst if k in dct)

另外一个选择是在迭代之前过滤lst

sum(dct[k] for k in filter(lambda i: i in dct, lst))

您可以在过滤列表中使用reduce function作为sum的替代方法:

reduce(lambda a, k: a + dct[k], filter(lambda i: i in dct, lst))

现在让我们通过timeit找到最快的方法:

from timeit import timeit
import random

lst = range(0, 10000)
dct = {x:x for x in lst if random.choice([True, False])}

via_sum = lambda:(sum(dct.get(k, 0) for k in lst))
print("Via sum and get: %s" % timeit(via_sum, number=10000))
# Via sum and get: 16.725695848464966

via_sum_and_cond = lambda:(sum(dct[k] for k in lst if k in dct))
print("Via sum and condition: %s" % timeit(via_sum_and_cond, number=10000))
# Via sum and condition: 9.4715681076

via_reduce = lambda:(reduce(lambda a, k: a + dct[k], filter(lambda i: i in dct, lst)))
print("Via reduce: %s" % timeit(via_reduce, number=10000))
# Via reduce: 19.9522120953

所以最快的选择是通过生成器表达式中的if语句对项目进行求和

sum(dct[k] for k in lst if k in dct) # Via sum and condition: 9.4715681076

祝你好运!