Add nested dictionaries on matching keys

Viewed 99

I have a nested dictionary, such as:

{'A1': {'T1': [1, 3.0, 3, 4.0], 'T2': [2, 2.0]}, 'A2': {'T1': [1, 0.0, 3, 5.0], 'T2': [2, 3.0]}}

What I want to do is sum each sub dictionary, to obtain this:

A1 A2  A1 A2
T1+T1  T2+T2 (ignore the first entry of the list)
 [3.0, 5.0, 9.0] <<<< output
   1    2    3
res 3.0 + 0.0 = 3.0  and 2.0 + 3.0 = 5.0 and  5.0 + 4.0 = 9.0

How can I do this? I've tried a for, but I've created a big mess

2 Answers

One way is to use collections.Counter in a list comprehension, and sum the resulting Counter objects:

from collections import Counter
d = {'A1': {'T1': 3.0, 'T2': 2.0}, 'A2': {'T1': 0.0, 'T2': 3.0}} 

l = (Counter(i) for i in d.values())
sum(l, Counter())
# Counter({'T1': 3.0, 'T2': 5.0})

For sum to work here, I've defined an empty Counter() as the start argument, so sum expects other Counter objects.

To get only the values, you can do:

sum(l, Counter()).values()
# dict_values([3.0, 5.0])

you could use a list comprehension with zip:

d = {'A1': {'T1': 3.0, 'T2': 2.0}, 'A2': {'T1': 0.0, 'T2': 3.0}} 
[sum(e) for e in zip(*(e.values() for e in d.values()))]

output:

[3.0, 5.0]

this will work if your python version is >= 3.6

also, you can use 2 for loops:

r = {}
for dv in d.values():
    for k, v in dv.items():
        r.setdefault(k, []).append(v)
result = [sum(v) for v in r.values()]
print(result)

output:

[3.0, 5.0]

after your edit

you could use:

from itertools import zip_longest

sum_t1, sum_t2 = list(list(map(sum, zip(*t))) for t in zip(*[e.values() for e  in d.values()]))
[i for t in zip_longest(sum_t1[1:], sum_t2[1:]) for i in t if i is not None]

output:

[3.0, 5.0, 6, 9.0]
Related