在字典理解中求和而不是覆盖值

Summing instead of overriding values in dictionary comprehension

当字典理解中的键相同时,我希望将它们的值相加。例如,

>>> dct = {-1: 1, 0: 2, 1: 3}
>>> {k**2: v for k, v in dct.items()}
{1: 3, 0: 2}

但是,我想得到的是{1: 4, 0: 2},因为1和-1的平方都是1,1 + 3 = 4。

显然,我可以用 for 循环来完成,但是有 shorthand 吗?

没有 shorthand 版本,因为您的理解需要跟踪当前状态,这是不可行的。就像你说的,答案是 for 循环:

old = {-1: 1, 0: 2, 1:3}
new = {}
for k, v in old.items():
    new[k**2] = new.get(k**2, 0) + v

使用 dict.get 方法的技巧我在 Python 文档的某处看到。它做同样的事情:

if k**2 in new:
   new[k**2] += v
else:
   new[k**2] = v

但此变体使用 get 方法,该方法 returns 将默认值 0 添加到将分配的值(当键不存在时)。因为它是 0,而且值是相加的数字,所以 0 没有效果。相比之下,如果您需要获取产品,您会使用 1 作为默认值,因为从 0 开始意味着您永远不会增加该值。

此外,上面显示的后者更冗长,每个周期计算 k**2 两次,这会耗尽计算。要使其使用 1 次计算,需要 另一 行代码,在我看来,当 get 方法如此简洁时,这不值得花时间。

计算总和的最快方法之一是使用 defaultdict - 自初始化字典:

from collections import defaultdict
new = defaultdict(int)
for k, v in old.items():
    new[k**2] += v