Python字典聚合问题:functools.reduce为何忽略负数值?
问题解答
为什么代码会移除负数值对应的键
这个问题和functools.reduce、operator.add本身没有关系,核心原因是**collections.Counter重写的__add__方法有特殊设计逻辑**:
Counter实例执行加法操作时,只会保留最终计数结果大于0的键,结果小于等于0的键会被直接丢弃。
你示例中154对应的值为-0.1,在Counter相加过程中最终结果为负,因此被自动过滤,这是Counter的专属特性,和普通数值加法的逻辑不一致。
可实现期望输出的替代方案
方案1:collections.defaultdict遍历累加
逻辑最清晰直观,天然兼容正负值:
from collections import defaultdict d = [{152: 1}, {151: 3}, {152: 4}, {153: 5}, {153: 10}, {154: -0.1}] res = defaultdict(float) for item in d: for k, v in item.items(): res[k] += v # 如需输出普通字典可加下行 res = dict(res)
运行结果为{152: 5, 151: 3, 153: 15, 154: -0.1},完全符合预期。
方案2:functools.reduce自定义合并逻辑
如果偏好函数式写法,可以避开Counter的加法规则,自己定义合并逻辑:
import functools d = [{152: 1}, {151: 3}, {152: 4}, {153: 5}, {153: 10}, {154: -0.1}] res = functools.reduce(lambda a, b: {k: a.get(k, 0) + b.get(k, 0) for k in {*a, *b}}, d)
方案3:Counter的update方法实现
如果需要使用Counter,可调用不会过滤负值的update方法实现:
from collections import Counter d = [{152: 1}, {151: 3}, {152: 4}, {153: 5}, {153: 10}, {154: -0.1}] res = Counter() for item in d: # update为直接累加操作,不会过滤负值 res.update(item) # 如需输出普通字典可加下行 res = dict(res)
内容的提问来源于stack exchange,提问作者koyamashinji
相关产品推荐
相关产品推荐

