将字典列表合并为单个字典,为通用键添加值

时间:2020-04-22 11:16:26

标签: python list dictionary merge

我该如何列出这样的词典

dico = [{'a':1}, {'b':2}, {'c':1}, {'d':2}, {'e':2}, {'d':3}, {'g':1}, {'h':4}, {'h':2}, {'f':6}, {'a':2}, {'b':2}]

变成这样的单个字典

{'a':3, 'b':4, 'c':1, 'd':5,'e':2,'f':6 , 'g':1 ,'h':6}

此刻

result = {}
for d in dico:
  result.update(d)
print(result)

结果:

{'a': 2, 'b': 2, 'c': 1, 'd': 3, 'e': 2, 'g': 1, 'h': 2, 'f': 6}

5 个答案:

答案 0 :(得分:4)

只需将您的词典替换为collections.Counter,它就会起作用:

from collections import Counter

dico = [{'a':1}, {'b':2}, {'c':1}, {'d':2}, {'e':2}, {'d':3}, {'g':1}, {'h':4}, {'h':2}, {'f':6}, {'a':2}, {'b':2}]

result = Counter()
for d in dico:
    result.update(d)
print(result)

输出:

Counter({'h': 6, 'f': 6, 'd': 5, 'b': 4, 'a': 3, 'e': 2, 'c': 1, 'g': 1})

为什么上述方法与docs中的update的{​​{1}}配合使用:

元素是从另一个映射(或计数器)的可迭代次数或添加的次数中计数的。类似于dict.update(),但添加计数而不是替换计数。另外,可迭代对象应该是元素序列,而不是(键,值)对序列。

答案 1 :(得分:3)

这是一种使用collections.Counter(一种字典)的理想方法:

from collections import Counter

def add_dicts(dicts):
    return sum(map(Counter, dicts), Counter())

上面的方法对于大量词典而言效率不高,因为它为结果创建了许多中间Counter对象,而不是就地更新一个结果,因此它以二次时间运行。这是一个线性运行的类似解决方案:

from collections import Counter

def add_dicts(dicts):
    out = Counter()
    for d in dicts:
        out += d
    return out

答案 2 :(得分:3)

使用defaultdict

from collections import defaultdict
dct = defaultdict(int)

for element in dico:
    for key, value in element.items():
        dct[key] += value

print(dct)

哪个产量

defaultdict(<class 'int'>, 
    {'a': 3, 'b': 4, 'c': 1, 'd': 5, 'e': 2, 'g': 1, 'h': 6, 'f': 6})


关于时间测量,这是四个答案之间的比较:

from collections import defaultdict, Counter
from timeit import timeit

def solution_dani():
    result = sum((Counter(e) for e in dico), Counter())

def solution_kaya():
    return sum(map(Counter, dico), Counter())

def solution_roadrunner():
    result = Counter()
    for d in dico:
        result.update(d)
    return result

def solution_jan():
    dct = defaultdict(int)
    for element in dico:
        for key, value in element.items():
            dct[key] += value
    return dct

print(timeit(solution_dani, number=10000))
print(timeit(solution_kaya, number=10000))
print(timeit(solution_roadrunner, number=10000))
print(timeit(solution_jan, number=10000))

在我的MacBookAir上产生了

0.839742998
0.8093687279999999
0.18643740100000006
0.04764247300000002

因此,默认字典的解决方案是最快的(系数15-20),其次是@RoadRunner。

答案 3 :(得分:2)

使用collections.Countersum

from collections import Counter

dico = [{'a':1}, {'b':2}, {'c':1}, {'d':2}, {'e':2}, {'d':3}, {'g':1}, {'h':4}, {'h':2}, {'f':6}, {'a':2}, {'b':2}]


result = sum((Counter(e) for e in dico), Counter())
print(result)

输出

Counter({'h': 6, 'f': 6, 'd': 5, 'b': 4, 'a': 3, 'e': 2, 'c': 1, 'g': 1})

如果您需要严格的字典,请执行以下操作:

result = dict(sum((Counter(e) for e in dico), Counter()))
print(result)

您可以这样修改自己的方法:

result = {}
for d in dico:
    for key, value in d.items():
        result[key] = result.get(key, 0) + value

print(result)

update方法将替换文档中现有键的值:

使用其他键/值对更新字典,覆盖 现有密钥。

答案 4 :(得分:1)

import collections

counter = collections.Counter()

for d in dico:
    counter.update(d)

result = dict(counter)
print(result)

输出

{'a': 3, 'b': 4, 'c': 1, 'd': 5, 'e': 2, 'g': 1, 'h': 6, 'f': 6}