1

I have 2 dictionaries that share about 80% the same keys and the values are 2 element lists. I need to make a new dictionary out of the three that will contain all the keys, including the ones unique to each dictionary and I need the values of the same keys to be summed up.

    dict1 = {'Mike': [10,20], 'John': [12,34], 'Steve': [60,10]}
    dict2 = {'Mike': [15,10], 'John': [18,36]}

The new dictionary should look like this :

    dict3 = {'Mike': [25,30], 'John': [30,70], 'Steve': [60,10]}

Any idea how I should tackle this ?

5 Answers5

3

There are lots of ways to do this, but here is a way that minimizes lookups, which may be helpful if the actual dicts are large:

keys_1 = set(dict1.keys())
keys_2 = set(dict2.keys())
all_keys = keys_1 | keys_2
for key in all_keys:
    a,b = 0,0
    if key in keys_1:
        a += dict1[key][0]
        b += dict1[key][1]
    if key in keys_2:
        a += dict2[key][0]
        b += dict2[key][1]
    dict3[key] = [a,b]
3

Here's my attempt at a somewhat functional solution for any number of dicts and any number of values to zip-sum.

Define how you want to merge entries. In this case by summing the individual components, materializing the result:

merge = lambda vs: list(map(sum, zip(*vs)))

Then define how to merge two dicts:

def merge_dicts(ds):
    keys = set.union(*map(set, ds))
    return {k: merge(map(lambda d: d.get(k, repeat(0)), ds))
            for k in keys}

Here I just go over the union of all keys, merging every dict's entry, with repeat(0) as default so merge() will just sum up zeroes for missing values.

After that you can merge your dicts like this:

merged = merge_dicts([dict1, dict2])
Felk
  • 7,720
  • 2
  • 35
  • 65
  • Would it be possible to re-use this code for Dict[str: int] or would I have to write something else? ints aren't iterable of course, but I'm wondering if the modification would be easy / simple. – Raf Jul 07 '23 at 12:36
2

Take keys from both dicts, iterate through and populate dict3 depending on where that key in both_key belongs to

both_keys = set(list(dict1.keys()) + list(dict2.keys()))
dict3 = {}
for k in both_keys:
    if k in dict1 and k in dict2:
        dict3[k] = [sum(x) for x in zip(dict1[k], dict2[k])]
    elif k in dict1:
        dict3[k] = dict1[k]
    else:
        dict3[k] = dict2[k]
jimmu
  • 1,025
  • 1
  • 10
  • 15
1

my solution use numpy :

import numpy as np
sum_dict = {}
for key in set(dict1.keys() + dict2.keys()):
    sum_dict[key] = np.add(dict1.get(key, np.zeros(2)), dict2.get(key, np.zeros(2)))
  1. concatenate all the 2 keys
  2. loop and using numpy add to sum the values, and the default value is a numpy array of zeros

And convert back to dict of list if you want

dict([(k,list(v)) for (k,v) in sum_dict.items()])
Out[99]:
{'John': [30, 70], 'Mike': [25, 30], 'Steve': [60.0, 10.0]}
Espoir Murhabazi
  • 5,973
  • 5
  • 42
  • 73
1

Try this:

dict1 = {'Mike': [10,20], 'John': [12,34], 'Steve': [60,10]}
dict2 = {'Mike': [15,10], 'John': [18,36]}

new_dict = {}

for x, y in dict1.items():
if x in dict2.keys():
    new_dict[x] = [a + b for a, b in zip(dict2[x], dict1[x])]
else:
    new_dict[x] = dict1[x]
print(new_dict)

#Output : {'Mike': [25, 30], 'John': [30, 70], 'Steve': [60, 10]}
Sagar Dawda
  • 1,126
  • 9
  • 17