Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

combining two python dictionaries into one when the net values are not positive [duplicate]

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?

like image 419
user3314562 Avatar asked Feb 21 '15 13:02

user3314562


People also ask

How do you combine multiple dictionaries into one in Python?

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 (|=).

How do you append a dictionary?

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.


2 Answers

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.

like image 57
Martijn Pieters Avatar answered Oct 10 '22 20:10

Martijn Pieters


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}
like image 41
Roope Avatar answered Oct 10 '22 21:10

Roope