过滤器值的表达式

问题描述:

我有一个字典dct为此,我想它的每个值要进行求和提供了一种在指定列表存在lst它们相应的密钥。过滤器值的表达式

我使用至今的代码是:

sum(dct[k] for k in lst) 

在上述发电机表达我想处理KeyError的情况下,从列表中的一个关键的字典里是找不到的。我似乎无法找到如何在此生成器表达式中实现(按语法)try - except方法或者if - else方法。

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

+1

您不能在生成器表达式中使用'try'。为什么不使用'dct.get(k)',如果找不到密钥,会给你'None'而不是错误?在没有找到密钥的情况下(例如,它应该计为“0”),代码的正确行为是什么? – jonrsharpe

+0

如果找不到密钥,则应继续使用其余密钥。 (我会更新我的描述来解释这种情况 - 感谢您注意到这一点) – Yannis

嗯,有几个选项,首选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 

所以最快的选项是通过如内声明,总结项目发生器表达

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

好Luc k!

+0

伟大而完整的答案。好奇的是,如果你能够提供一些洞察力来比较这4个选项;具体来说,第三个选项与前两个选项相比如何。他们之间是否有任何提高效率的方法或更多的“Pythonic”方法? – Yannis

+0

@Yannis谢谢,当然)看到更新的答案与时间指标:)我的猜测赢家方法是最'Pythonic')) –

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

确实有用的答案;其他人也提到了这种方法,并且从我所看到的情况来看,你的并不是最快的。对不起 – Yannis

您可以简单地使用.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 

你有两个选择:

检查如果该键存在

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

您可以使用字典的get - 方法,提供一个默认值,如果没有找到:

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