I have two python dictionaries that I'm trying to sum the values together on. The answer in: Is there any pythonic way to combine two dicts (adding values for keys that appear in both)? gets me most of the way. However I have cases where the net values may be zero or negative but I still want the values in the final dictionary. Even though Counters will accept negative values, it will only output a value if it's greater than zero.
Example
from collections import Counter
A = Counter({'a': 1, 'b': 2, 'c': -3, 'e': 5, 'f': 5})
B = Counter({'b': 3, 'c': 4, 'd': 5, 'e': -5, 'f': -6})
C = A + B
print(C.items())
Output: [('a', 1), ('c', 1), ('b', 5), ('d', 5)]
c = -3 + 4 = 1
is correct so the negative input is not an issue but e:0 and f:-1 are missing from the output
How can I perform the summation and get all values output?
Python 3.9 has introduced the merge operator (|) in the dict class. Using the merge operator, we can combine dictionaries in a single line of code. We can also merge the dictionaries in-place by using the update operator (|=).
Appending element(s) to a dictionary To append an element to an existing dictionary, you have to use the dictionary name followed by square brackets with the key name and assign a value to it.
Summing drops values at 0 and lower, yes, as documented:
Several mathematical operations are provided for combining Counter objects to produce multisets (counters that have counts greater than zero). Addition and subtraction combine counters by adding or subtracting the counts of corresponding elements. Intersection and union return the minimum and maximum of corresponding counts. Each operation can accept inputs with signed counts, but the output will exclude results with counts of zero or less.
[...]
- The multiset methods are designed only for use cases with positive values. The inputs may be negative or zero, but only outputs with positive values are created. There are no type restrictions, but the value type needs to support addition, subtraction, and comparison.
You'll need to use Counter.update()
if you wanted to retain the values at 0 or lower. Since this is an in-place operation you'll have to create a copy here:
>>> from collections import Counter
>>> A = Counter({'a': 1, 'b': 2, 'c': -3, 'e': 5, 'f': 5})
>>> B = Counter({'b': 3, 'c': 4, 'd': 5, 'e': -5, 'f': -6})
>>> C = A.copy()
>>> C.update(B)
>>> C
Counter({'b': 5, 'd': 5, 'a': 1, 'c': 1, 'e': 0, 'f': -1})
If preserving A
wasn't a goal, you can just update it directly.
How about something like:
dict((x, a.get(x, 0) + b.get(x, 0)) for x in set(a)|set(b))
example:
>>> a = {'a':1, 'b':2, 'c':-3, 'e':5, 'f': 5}
>>> b = {'b':3, 'c':4, 'd':5, 'e':-5, 'f': -6}
>>>
>>> dict((x, a.get(x, 0) + b.get(x, 0)) for x in set(a)|set(b))
{'e': 0, 'a': 1, 'f': -1, 'd': 5, 'c': 1, 'b': 5}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With