4

I want to merge all the dictionaries in a dictionary, while ignoring the main dictionary keys, and summing the value of the other dictionaries by value.

Input:

{'first':{'a': 5}, 'second':{'a': 10}, 'third':{'b': 5, 'c': 1}}

Output:

{'a': 15, 'b': 5, 'c': 1}

I did:

def merge_dicts(large_dictionary):
    result = {}
    for name, dictionary in large_dictionary.items():
        for key, value in dictionary.items():
            if key not in result:
                result[key] = value
            else:
                result[key] += value
    return result

Which works, but I don't think it's such a good way (or less "pythonic").

By the way, I don't like the title I wrote. If anybody thinks of a better wording please edit.

bhansa
  • 6,780
  • 2
  • 27
  • 49
sheldonzy
  • 4,613
  • 9
  • 43
  • 74

3 Answers3

6

You can sum counters, which are a dict subclass:

>>> from collections import Counter
>>> sum(map(Counter, d.values()), Counter())
Counter({'a': 15, 'b': 5, 'c': 1})
wim
  • 302,178
  • 90
  • 548
  • 690
2

This will work

from collections import defaultdict
values = defaultdict(int)
def combine(d, values):
    for k, v in d.items():
        values[k] += v

for v in a.values():
    combine(v, values)

print(dict(values))
daemon24
  • 1,357
  • 1
  • 11
  • 23
  • I hadn't put list in defaultdict, i had put defaultdict(lambda : 0), defaultdict(int) and defaultdict(lambda : 0) result to same. But int will be more pythonic, i also thought. – daemon24 Nov 03 '17 at 19:27
  • @wim Oh. Hmm. I thought it would always return the same list. But it doesn't. Gotta think this through when I have more time. Thanks for the correction. – Stefan Pochmann Nov 03 '17 at 19:35
  • @wim Yeah ok I'm an idiot... wouldn't have expected `def f(): return []` to always return the same one. Something about `defaultdict(lambda: [])` somehow threw me off. I guess because it looks too similar to parameter default notation. – Stefan Pochmann Nov 03 '17 at 19:47
0

Almost similar, but it's just short and I like it a little better.

def merge_dicts(large_dictionary):
    result = {}
    for d in large_dictionary.values():
        for key, value in d.items():
            result[key] = result.get(key, 0) + value
    return result
wpercy
  • 9,141
  • 4
  • 33
  • 42
harshil9968
  • 3,108
  • 1
  • 13
  • 26