3

I have a dictionary defined as such:

dict: {'KEY1': Decimal('-6.20000'), 'KEY2': Decimal('-2.58000'), 'KEY3': Decimal('6.80000')}

and I want to have either a list or an OrderedDict of the key/value pairs ordered by absolute value.

I tried:

sorted_dict = sorted(mydict, key=lambda k: abs(mydict[k]), reverse=True)

But this only returns a list of the keys, without the corresponding values, although they do seem to be sorted by the absolute values.

How can I get an OrderedDict or a list of tuples containing both the key and the values, but sorted by the absolute value?

5
  • sorted((abs(k), v) for k, v in d.items(), reverse=True) Is one way Commented Oct 11, 2017 at 3:52
  • I get an error: sorted_dict = sorted((abs(k), v) for k, v in dict.items(), reverse=True) ^ SyntaxError: Generator expression must be parenthesized if not sole argument Commented Oct 11, 2017 at 4:08
  • And when I change it to sorted_dict = sorted(((abs(k), v) for k, v in dict.items()), reverse=True) I get another error: Trade loop error: (<class 'TypeError'>, TypeError("bad operand type for abs(): 'str'",), <traceback object at 0x000001466D7DCE08>) Commented Oct 11, 2017 at 4:09
  • My bad, try sorted((abs(v), k) for k, v in d.items(), reverse=True) Commented Oct 11, 2017 at 4:12
  • So this gives me a list of tuples with items of key and absolute value. What I want is a list that contains the original values(negatives as well), but sorted by absolute value. It also gives a list of tuples with the value first and the key second, which is not what is expected Commented Oct 11, 2017 at 4:17

2 Answers 2

2

You're on the right track. Use .items and pass the resulting tuple pairs into the OrderedDict constructor.

from collections import OrderedDict

values = {
    'KEY1': Decimal('-6.20000'),
    'KEY2': Decimal('-2.58000'),
    'KEY3': Decimal('6.80000')
}

sorted_pairs = sorted(values.items(), key=lambda k: abs(k[1]), reverse=True)
ordered_dict = OrderedDict(sorted_pairs)
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks. This is the same answer as PM 2Ring's. I see it was posted at around the same time, so I guess you hadn't seen his yet. I already accepted his answer, but thanks for the input :)
Technically the timestamps say that mine was posted first by about half an hour... But either way, I'm glad you got your question answered :)
Oh absolutely, I'm not sure why I missed it! Put yours as the correct answer :)
2

You just need a key function that receives a (key, value) tuple from the dictionary .items() View and returns the absolute value of that value. Eg:

from decimal import Decimal
from collections import OrderedDict

data = {'KEY1': Decimal('-6.20000'), 'KEY2': Decimal('-2.58000'), 'KEY3': Decimal('6.80000')} 
out = OrderedDict(sorted(data.items(), key=lambda t: abs(t[1])))
print(out)

output

OrderedDict([('KEY2', Decimal('-2.58000')), ('KEY1', Decimal('-6.20000')), ('KEY3', Decimal('6.80000'))])

It's a little easier to read if we use a proper def function for the key function:

def keyfunc(t):
    return abs(t[1])

out = OrderedDict(sorted(data.items(), key=keyfunc))

3 Comments

Works perfect, thanks! At first I thought the OrderedDict conversion messed up the order, but this is simply how the eclipse debugger shows it- it reorders the dict entries by key name... Printing it to the console output shows the correct order.
@VincentL Ah! Yes, there are a couple of IDEs that "helpfully" sort dictionaries by key when they display them. But you'd think they'd be smart enough to not sort OrderedDicts...
@VincentL On a related note, take a look at Using an OrderedDict in **kwargs

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.