0

Given any amount of dictionaries, how would one go about merging them all together, such that the merged dictionary contains all the dictionaries' elements as well as summing similar key values.

eg.

d1 = {a: 2, b: 3, c: 1}
d2 = {a: 3, b: 2, c: 3}
d3 = {b: 8, d: 2}

our merged dictionary would look like such:

{a: 5, b: 13, c: 4, d: 2}

Can this be done via kwargs? I am aware that one can do:

{**d1, **d2, **d3}

But can this be done for n-defined dictionaries?

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Orange Receptacle
  • 1,173
  • 3
  • 19
  • 40
  • Even if kwargs could be applied to an unlimited number of dictionaries, I don't think it would be a good idea to use it here, since it doesn't add up keys, it discards them. Your `{**d1, **d2, **d3}` expression evaluates to `{'a': 3, 'b': 8, 'c': 3, 'd': 2}`, not `{a: 5, b: 13, c: 4, d: 2}`. – Kevin Aug 01 '19 at 17:54
  • Your expected output doesn't seem to line up with the input you posted. Shouldn't it be `{a: 5, b: 13, c: 4, d: 2}`? – benvc Aug 01 '19 at 18:07
  • Yes, thank you - I've updated it accordingly – Orange Receptacle Aug 01 '19 at 18:10

2 Answers2

2

you can use a Counter

from collections import Counter

d1 = {'a': 2, 'b': 3, 'c': 1}
d2 = {'a': 3, 'b': 2, 'c': 3}
d3 = {'b': 8, 'd': 2}

list_of_dicts = [d1, d2, d3]

cnt = Counter()

for d in list_of_dicts:
    cnt.update(d)

print(cnt)

Counter({'b': 13, 'a': 5, 'c': 4, 'd': 2})
Raphael
  • 1,731
  • 2
  • 7
  • 23
  • How does this fare against a `defaultdictionary(int)`? From what I can tell, order doesn't matter when using a Counter, whereas order is maintained via a defaultdict – Orange Receptacle Aug 01 '19 at 18:12
  • 1
    @OrangeReceptacle - `Counter` and `defaultdict` are both subclasses of `dict` so I would expect ordering behavior to be the same (but note that order in this case is dependent on which version of Python you are using as well as the insertion order that results from the loop or other approach you use to create the `Counter` or `defaultdict`). – benvc Aug 01 '19 at 18:19
  • dictionaries are not sensitive to order themselves so I would neither expect defaufltdict nor counter to be – Raphael Aug 01 '19 at 18:22
  • 1
    @Raphael - actually that depends on Python version, see https://stackoverflow.com/questions/39980323/are-dictionaries-ordered-in-python-3-6 – benvc Aug 01 '19 at 18:23
  • @benvc this is interesting. Thanks! – Raphael Aug 01 '19 at 18:28
0

Per your comment regarding defaultdict, here is an approach along those lines. That said, I prefer the Counter approach in the answer from @Raphael.

from collections import defaultdict

def mergesum(*dicts):
    merged = defaultdict(int) 
    for k, v in (item for d in dicts for item in d.items()):
        merged[k] += v

    return merged


d1 = {'a': 2, 'b': 3, 'c': 1}
d2 = {'a': 3, 'b': 2, 'c': 3}
d3 = {'b': 8, 'd': 2}

result = mergesum(d1, d2, d3)
print(result)
# defaultdict(<class 'int'>, {'a': 5, 'b': 13, 'c': 4, 'd': 2})
benvc
  • 14,448
  • 4
  • 33
  • 54