Home > Back-end >  Sorting dictionary - functools.reduce ignores negative values?
Sorting dictionary - functools.reduce ignores negative values?

Time:12-06

I have a dictionary like below:

d = [{152: 1}, {151: 3}, {152: 4}, {153: 5}, {153: 10}, {154: -0.1}]

I want to sort them like below:

{151: 3, 152: 5, 153: 15, 154: -0.1}

I tried the below by following this answer ...

sorted = dict(functools.reduce(operator.add, map(collections.Counter, d)))

The output I got is :

{151: 3, 152: 5, 153: 15}

I do not understand why functools.reduce(operator.add, ) removes the {154: -0.1}. Isn't operator.add just a plain summation method?

operator.add(a, b)
operator.add(a, b)
Return a b, for a and b numbers.

Questions

  • What could be the workaround to achieve the desired output?
  • Why does functools.reduce(operator.add, ) remove the negative value?

CodePudding user response:

The Counter class is designed for positive counts so -0.1 is treated as 0 by its addition method (as would any other negative result). You could do this using a loop and a regular dictionary (no library needed):

dicts = [{152: 1}, {151: 3}, {152: 4}, {153: 5}, {153: 10}, {154: -0.1}]

r = dict()
for d in dicts:
    r.update({k:r.get(k,0) v for k,v in d.items()})

print(r)
{152: 5, 151: 3, 153: 15, 154: -0.1}

The documentation for Counter states that Each operation can accept inputs with signed counts, but the output will exclude results with counts of zero or less

CodePudding user response:

A pandas solution

>>>import pandas as pd
>>>d = [{152: 1}, {151: 3}, {152: 4}, {153: 5}, {153: 10}, {154: -0.1}]
>>>pd.DataFrame(d).sum().to_dict()
{152: 5.0, 151: 3.0, 153: 15.0, 154: -0.1}

CodePudding user response:

operator.add is a plain summation method, please see its source code: operator.add


Why does functools.reduce(operator.add, ) remove the negative value?

Your one-line code is equivalent to Counter({152: 1}) Counter({151: 3}) Counter({152: 4}) Counter({153: 5}) Counter({153: 10}) Counter({154: -0.1})

However, the add method for Counter will remove negative values, check its source: counter-add

Thus, the value for key 154 will be ignored.


How to make your work done?

t = {}
for i in d:
    for k in i.keys():
        t[k] = t[k] i[k] if k in t else i[k]
  • Related