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
Read and Write CSV Files Including Unicode with Python 2.7
Remove Punctuation from Unicode Formatted Strings
Matplotlib Scatter Plot Legend
Run Python Script Without Windows Console Appearing
How to Add Placeholder to an Entry in Tkinter
How to Print Variables Without Spaces Between Values
Pandas - Plotting a Stacked Bar Chart
Differencebetween 'Same' and 'Valid' Padding in Tf.Nn.Max_Pool of Tensorflow
How to Trim Whitespace from a String
How to Get First Element in a List of Tuples
Python Sharing a Lock Between Processes