You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

字典推导时检查键是否存在并实现同键值求和的最优方法

嘿,这个问题我太熟了!先给你划个重点:字典推导其实不是处理这种「按键累积求和」需求的最优选择——因为推导式是一次性生成键值对的声明式语法,没法在推导过程中修改已经生成的键对应的值。下面给你几个实用的方案,按可读性和效率排序:

最优方案1:普通for循环(最直观,无额外依赖)

这是最直接的写法,新手也能一眼看懂,而且性能拉满:

items = [('a', 1), ('b', 2), ('a', 3), ('c', 4), ('b', 5)]
result = {}
for key, value in items:
    if key in result:
        result[key] += value
    else:
        result[key] = value
# 最终结果: {'a':4, 'b':7, 'c':4}

这里完美实现了你想要的「检查键是否存在+else分支」逻辑,比硬套字典推导灵活得多,还能随时加额外的处理逻辑。

最优方案2:用collections.defaultdict(更简洁)

如果不想写if-else判断,可以用Python标准库的defaultdict,它会自动给不存在的键设置默认值(这里我们用int,默认值就是0):

from collections import defaultdict

items = [('a', 1), ('b', 2), ('a', 3), ('c', 4), ('b', 5)]
result = defaultdict(int)
for key, value in items:
    result[key] += value

# 要是需要转成普通字典(可选操作)
result = dict(result)

这个写法更简洁,省去了手动检查键的步骤,和普通循环效率几乎一样,是日常开发里最常用的方法。

备选方案:itertools.groupby(仅适合有序数据)

如果你的原始数据已经按item[0]排序好,可以用itertools.groupby来分组求和:

from itertools import groupby
from operator import itemgetter

# 注意:数据必须先按key排序,否则groupby会把不连续的相同键当成不同组
items = [('a', 1), ('a', 3), ('b', 2), ('b', 5), ('c', 4)]
result = {
    key: sum(v for _, v in group)
    for key, group in groupby(items, key=itemgetter(0))
}

但要注意:groupby只会把连续相同的键分到一组,如果数据没排序,会导致求和错误。而且排序会带来O(n log n)的时间开销,所以如果数据未排序,不如用前面两种O(n)时间复杂度的方法。

为什么不推荐硬套字典推导?

硬要在字典推导里实现的话,只能用一些违背设计初衷的hack(比如借助可变对象保存状态),比如:

items = [('a', 1), ('b', 2), ('a', 3), ('c', 4), ('b', 5)]
result = {}
{result.__setitem__(key, result.get(key, 0) + value) for key, value in items}

这种写法可读性极差,还利用了推导式的副作用操作,完全不符合Python的代码风格,绝对不推荐。

总结一下:日常开发优先选defaultdict或者普通for循环,前者简洁,后者无额外依赖;如果数据已排序,groupby可以作为备选,但记得先排序。

内容的提问来源于stack exchange,提问作者jsstuball

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:00:18