过滤 Python 生成器表达式中的值
Filter values inside Python generator expressions
我有一个字典 dct
,我希望对它的每个值求和,前提是它们的对应键存在于指定列表 lst
。
目前我使用的代码是:
sum(dct[k] for k in lst)
在上面的生成器表达式中,我想处理 KeyError
以防在字典中找不到列表中的键。我似乎找不到如何在这个生成器表达式中实现(语法方面)try
-except
方法,也找不到 if
-else
方法。
如果在字典中找不到列表中的 键,则应继续获取其他值。 求和的最终结果不应受到任何缺失键的影响。如果存在 none 个键,则总和的结果应为零。
sum(dct[k] for k in lst if k in dct)
您可以简单地使用 .get()
尝试从字典中获取键的值,如果找不到,将 return 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)
returns dct[k]
如果 k
是 dct
中的键,如果不是 0
。
您可以使用get
-字典的方法,如果找不到则提供默认值:
sum(dct.get(k, 0) for k in lst)
好吧,选项很少,首选是使用 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
祝你好运!
我有一个字典 dct
,我希望对它的每个值求和,前提是它们的对应键存在于指定列表 lst
。
目前我使用的代码是:
sum(dct[k] for k in lst)
在上面的生成器表达式中,我想处理 KeyError
以防在字典中找不到列表中的键。我似乎找不到如何在这个生成器表达式中实现(语法方面)try
-except
方法,也找不到 if
-else
方法。
如果在字典中找不到列表中的 键,则应继续获取其他值。 求和的最终结果不应受到任何缺失键的影响。如果存在 none 个键,则总和的结果应为零。
sum(dct[k] for k in lst if k in dct)
您可以简单地使用 .get()
尝试从字典中获取键的值,如果找不到,将 return 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)
returns dct[k]
如果 k
是 dct
中的键,如果不是 0
。
您可以使用get
-字典的方法,如果找不到则提供默认值:
sum(dct.get(k, 0) for k in lst)
好吧,选项很少,首选是使用 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
祝你好运!