Python:优雅地将字典与值的 sum() 合并

标签 python dictionary

我正在尝试合并来自多台服务器的日志。每个日志都是一个元组列表(datecount)。 date 可能出现不止一次,我希望结果字典包含来自所有服务器的所有计数的总和。

这是我的尝试,例如一些数据:

from collections import defaultdict

a=[("13.5",100)]
b=[("14.5",100), ("15.5", 100)]
c=[("15.5",100), ("16.5", 100)]
input=[a,b,c]

output=defaultdict(int)
for d in input:
        for item in d:
           output[item[0]]+=item[1]
print dict(output)

这给出了:

{'14.5': 100, '16.5': 100, '13.5': 100, '15.5': 200}

正如预期的那样。

我要疯了,因为一位同事看到了代码。她坚持认为,必须有一种更加 Pythonic 和优雅的方式来完成它,而无需这些嵌套的 for 循环。有什么想法吗?

最佳答案

我认为没有比这更简单的了:

a=[("13.5",100)]
b=[("14.5",100), ("15.5", 100)]
c=[("15.5",100), ("16.5", 100)]
input=[a,b,c]

from collections import Counter

print sum(
    (Counter(dict(x)) for x in input),
    Counter())

请注意,Counter(也称为多重集)是数据最自然的数据结构(一种元素可以多次属于的集合类型,或等价的 - 具有语义的映射Element -> OccurrenceCount。你可以一开始就使用它,而不是元组列表。


也可以:

from collections import Counter
from operator import add

print reduce(add, (Counter(dict(x)) for x in input))

使用 reduce(add, seq) 而不是 sum(seq, initialValue) 通常更灵活,并且允许您跳过传递多余的初始值。

请注意,您也可以使用 operator.and_ 来查找多重集合的交集而不是求和。


上述变体非常慢,因为每一步都会创建一个新的计数器。让我们解决这个问题。

我们知道 Counter+Counter 返回一个带有合并数据的新 Counter。这没关系,但我们想避免额外的创建。让我们使用 Counter.update 代替:

update(self, iterable=None, **kwds) unbound collections.Counter method

Like dict.update() but add counts instead of replacing them. Source can be an iterable, a dictionary, or another Counter instance.

这就是我们想要的。让我们用兼容 reduce 的函数来包装它,看看会发生什么。

def updateInPlace(a,b):
    a.update(b)
    return a

print reduce(updateInPlace, (Counter(dict(x)) for x in input))

这仅比 OP 的解决方案慢一点。

基准测试:http://ideone.com/7IzSx (感谢 astynax,更新了另一个解决方案)

(另外:如果你非常想要一个单行,你可以用 lambda x,y: x.update(y) 或 x 替换 updateInPlace它的工作方式相同,甚至被证明更快,但在可读性方面失败。不要:-))

关于Python:优雅地将字典与值的 sum() 合并,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11290092/

相关文章:

java - JdbcTemplate.queryforList() 返回值但 map.get 返回 null

python - 在 python 中进行 Squish 测试以测试 qt 应用程序

python - 进度条使用 tqdm 和多进程将代码减慢 5 倍

python - 将查询集传递给django inlineform中的foreignkeyfield

dictionary - 测试和处理映射中的多个键的惯用 Go 方式是什么?

python - 用字典填充字典键的最有效方法

python从列表列表中选择范围

python - '\python.exe' 没有 python

android - 在 android 中使用 google map api 菜单的可搜索自动完成

c++ - 在 header 中添加 typedef 时出错