Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python merge two counter objects, keeping the largest sum

Tags:

python

counter

If I have two counter objects and I would like to merge them, adding new values from one and keeping the largest count if the two counters contain the same values.

Counter a = { "apple":3, "peach":1, "pears":7, "watermelon":2, "grapes":7 }

Counter b = { "apple":12, "kiwi":9, "grapes":2, "pears":21, "pineapple":2, "oranges":2 }

#desired output
counter c = { "apple":12, "pears":21, "grapes":7 "peach":1, "watermelon":2, "pineapple":2, "oranges":2} 

Currently I've tried updating the counter but that seems to merge the two counters but sums their counts. I would just like to merge the counters and keep the largest value or add to the counter if there isn't one already.

like image 244
user1610950 Avatar asked Mar 11 '23 14:03

user1610950


2 Answers

After OP edited their question, the desired output can be achieved by simply using the bitwise or ('|') operator:

from collections import Counter

a = Counter({ "apple":3, "peach":1, "pears":7, "watermelon":2, "grapes":7 })

b = Counter({ "apple":12, "kiwi":9, "grapes":2, "pears":21, "pineapple":2, "oranges":2 })

c = a | b

print(c)
>> Counter({'pears': 21, 'apple': 12, 'kiwi': 9, 'grapes': 7, 'watermelon': 2, 'oranges': 2,
            'pineapple': 2, 'peach': 1})
like image 64
DeepSpace Avatar answered Mar 24 '23 14:03

DeepSpace


You could take distinct keys from each of the Counter's using inbuilt a&b, and use them to get your desired max logic like this:

Counter({key:max(a[key], b[key]) for key in a&b})

Here is a sample run:

>>> from collections import Counter
>>> a=Counter({ "apple":3, "peach":1, "pears":7, "watermelon":2, "grapes":7 })
>>> b=Counter({ "apple":12, "kiwi":9, "grapes":2, "pears":21, "pineapple":2, "oranges":2 })
>>> Counter({key:max(a[key], b[key]) for key in a&b})
Counter({'pears': 21, 'apple': 12, 'grapes': 7})
>>> 

Note that if you wanted the minimum for common elements that is already built in python with this construct:

>>> a&b
Counter({'pears': 7, 'apple': 3, 'grapes': 2})
>>> 
like image 37
riteshtch Avatar answered Mar 24 '23 13:03

riteshtch