过滤器值的表达式
我有一个字典dct
为此,我想它的每个值要进行求和提供了一种在指定列表存在lst
它们相应的密钥。过滤器值的表达式
我使用至今的代码是:
sum(dct[k] for k in lst)
在上述发电机表达我想处理KeyError
的情况下,从列表中的一个关键的字典里是找不到的。我似乎无法找到如何在此生成器表达式中实现(按语法)try
- except
方法或者if
- else
方法。
如果字典中没有找到列表中的键,则应该继续获取其他值。 总和的最终结果不应受任何丢失的键影响。如果没有任何键存在,那么零应该是总和的结果。
嗯,有几个选项,首选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!
伟大而完整的答案。好奇的是,如果你能够提供一些洞察力来比较这4个选项;具体来说,第三个选项与前两个选项相比如何。他们之间是否有任何提高效率的方法或更多的“Pythonic”方法? – Yannis
@Yannis谢谢,当然)看到更新的答案与时间指标:)我的猜测赢家方法是最'Pythonic')) –
您可以简单地使用.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)
您不能在生成器表达式中使用'try'。为什么不使用'dct.get(k)',如果找不到密钥,会给你'None'而不是错误?在没有找到密钥的情况下(例如,它应该计为“0”),代码的正确行为是什么? – jonrsharpe
如果找不到密钥,则应继续使用其余密钥。 (我会更新我的描述来解释这种情况 - 感谢您注意到这一点) – Yannis