Merge and Sum of Two Dictionaries

Is there any pythonic way to combine two dicts (adding values for keys that appear in both)?

Use collections.Counter:

>>> from collections import Counter
>>> A = Counter({'a':1, 'b':2, 'c':3})
>>> B = Counter({'b':3, 'c':4, 'd':5})
>>> A + B
Counter({'c': 7, 'b': 5, 'd': 5, 'a': 1})

Counters are basically a subclass of dict, so you can still do everything else with them you'd normally do with that type, such as iterate over their keys and values.

Merge and sum of two dictionaries

You didn't say how exactly you want to merge, so take your pick:

x = {'both1': 1, 'both2': 2, 'only_x': 100}
y = {'both1': 10, 'both2': 20, 'only_y': 200}

print {k: x.get(k, 0) + y.get(k, 0) for k in set(x)}
print {k: x.get(k, 0) + y.get(k, 0) for k in set(x) & set(y)}
print {k: x.get(k, 0) + y.get(k, 0) for k in set(x) | set(y)}

Results:

{'both2': 22, 'only_x': 100, 'both1': 11}
{'both2': 22, 'both1': 11}
{'only_y': 200, 'both2': 22, 'both1': 11, 'only_x': 100}

How can I merge and sum two dictionary key and items?

It's a recursive data structure; let's use recursion.

Edit: missed the python-2.6 tag, no dict comprehensions there. Edit2: Copy values in case they exist in only one of the two, otherwise you'll run into surprises with references to the same dictionary being inside two separate dictionaries.

import copy

def recursively_sum(var1, var2):
"""If var1 and var2 are ints, return their sum. Otherwise they are dicts
and we recursively sum for each key that is either in var1 or var2."""

if var1 is None:
return copy.deepcopy(var2)
elif var2 is None:
return copy.deepcopy(var1)
elif isinstance(var1, int):
return var1 + var2
else:
result = {}
for key in set(var1) | set(var2):
result[key] = recursively_sum(var1.get(key), var2.get(key))
return result

Merging dict of dicts and sum values

Make two functions like below:

def cal_sum(lst):
final_dict = dict()
for l in lst:
sum(final_dict,l)
return final_dict

def sum(final_dict,iter_dict):
for k, v in iter_dict.items():
if isinstance(v, dict):
sum(final_dict.setdefault(k, dict()), v)
elif isinstance(v, int):
final_dict[k] = final_dict.get(k, 0) + v

Calling the above code as follows produces the desired output:

>>> print(cal_sum([COUNTRY1, COUNTRY2, COUNTRY3]))
{'a': {'U': 12, 'W': 23, 'V': 34, 'Y': 33, 'X': 22, 'Z': 31}, 'c': 447, 'b': {'AA': {'AAa': 26, 'AAy': 22, 'AAx': 90, 'AAz': 45}, 'BB': {'BBa': 15, 'BBz': 33, 'BBy': 67, 'BBx': 45}}}

Python: Elegantly merge dictionaries with sum() of values

Doesn't get simpler than this, I think:

a=[("13.5",100)]
b=[("14.5",100), ("15.5", 100)]
c=[("15.5",100), ("16.5", 100)]
input=[a,b,c]

from collections import Counter

print sum(
(Counter(dict(x)) for x in input),
Counter())

Note that Counter (also known as a multiset) is the most natural data structure for your data (a type of set to which elements can belong more than once, or equivalently - a map with semantics Element -> OccurrenceCount. You could have used it in the first place, instead of lists of tuples.


Also possible:

from collections import Counter
from operator import add

print reduce(add, (Counter(dict(x)) for x in input))

Using reduce(add, seq) instead of sum(seq, initialValue) is generally more flexible and allows you to skip passing the redundant initial value.

Note that you could also use operator.and_ to find the intersection of the multisets instead of the sum.


The above variant is terribly slow, because a new Counter is created on every step. Let's fix that.

We know that Counter+Counter returns a new Counter with merged data. This is OK, but we want to avoid extra creation. Let's use Counter.update instead:

update(self, iterable=None, **kwds) unbound collections.Counter method

Like dict.update() but add counts instead of replacing them.
Source can be an iterable, a dictionary, or another Counter instance.

That's what we want. Let's wrap it with a function compatible with reduce and see what happens.

def updateInPlace(a,b):
a.update(b)
return a

print reduce(updateInPlace, (Counter(dict(x)) for x in input))

This is only marginally slower than the OP's solution.

Benchmark: http://ideone.com/7IzSx (Updated with yet another solution, thanks to astynax)

(Also: If you desperately want an one-liner, you can replace updateInPlace by lambda x,y: x.update(y) or x which works the same way and even proves to be a split second faster, but fails at readability. Don't :-))

Merge lists of dictionaries by summing values of the same key

Try this if you want to sum all values for unique 'name' in each dictionaries :

names = set([k['name'] for k in dict1+dict2])
dict3 = []
for name in names:
temp_val = []
for dict_ in dict1+dict2:
if dict_['name'] == name:
temp_val.append(dict_['value'])
dict3.append({'name': name, 'value' : sum(temp_val)})

OUTPUT :

[{'name': 'A', 'value': 16}, {'name': 'B', 'value': 5}, {'name': 'C', 'value': 12}]

Merge 2 dictionaries, and try to update the sum if there is common keys?

Other suggestions will work. But if you want to try this more Pythonic way: (or just being lazy ... ;-)

from collections import Counter

d3 = Counter(dict1) + Counter(dict2)

print(d3) # to confirm it

Output:

Counter({'Sheldon Cooper': 15600000, 'Dean Craig Pelton': 3500000, 'Barack Hussein Obama II': 1750000, 'Elizabeth Alexandra Mary': 250000, 'Christopher Larkin': 50000, 'Eyal Shani': 5000, 'Zhang Aiqin': 1000})

Flutter:How to merge two objects and sum the values of the same key?

Do forEach on the longest map and check if the small map contains the key if it does then update the value with the sum or add the new.

  map2.forEach((key, value) {
if (map1.containsKey(key)) {
map1[key] = value + map1[key]!;
} else {
map1[key] = map2[key]!;
}
});

map1 will be the final result.



Related Topics



Leave a reply



Submit