我有一个字典dct
,我希望它的每个值都可以求和,只要它们在指定的列表lst
中存在相应的键。
我目前使用的代码是:
sum(dct[k] for k in lst)
在上面的生成器表达式中,我想处理KeyError
,以防在列表中找不到列表中的键。我似乎无法在此生成器表达式中找到如何实现(语法方式)try
- except
方法或if
- else
方法。
如果在词典中找不到列表中的键,那么它应该继续获取其他值。 总和的最终结果不应受任何缺失键的影响。如果没有密钥存在,那么零应该是和的结果。
答案 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
祝你好运!