0

I have following dict :

{'a1': (45, 8.2), 'a2': (80, 3.2), 'a3': (50, 4.2), 'a4': (80, 2.2)}

To sort it, I do :

import operator
sorted_d = sorted(d.items(),key=operator.itemgetter(1),reverse= True)

and sorted_d is now:

[('a2', (80, 3.2)), ('a4', (80, 2.2)), ('a3', (50, 4.2)), ('a1', (45, 8.2))]

where as I want it to be :

[('a4', (80, 2.2)), ('a2', (80, 3.2)), ('a3', (50, 4.2)), ('a1', (45, 8.2))]

The first part of value to be in descending order and the second partof value to be in ascending order.

any idea to achieve the expected output?

rkatkam
  • 2,634
  • 3
  • 18
  • 29

1 Answers1

4

You'll need to provide a tuple to sort on. Negate the first entry to sort on to force a descending sort:

sorted(d.items(), key=lambda i: (-i[1][0], i[1][1]))

Note that the reverse=True argument is gone.

Demo:

>>> d = {'a1': (45, 8.2), 'a2': (80, 3.2), 'a3': (50, 4.2), 'a4': (80, 2.2)}
>>> sorted(d.items(), key=lambda i: (-i[1][0], i[1][1]))
[('a4', (80, 2.2)), ('a2', (80, 3.2)), ('a3', (50, 4.2)), ('a1', (45, 8.2))]

What we are doing here is simply exploit the fact that Python sequences are sorted lexicographically; if you are comparing two tuples, the first elements are compared, and only if they match the elements in the second position are considered, and so on. See the documentation on comparison expressions:

Tuples and lists are compared lexicographically using comparison of corresponding elements. [...] If not equal, the sequences are ordered the same as their first differing elements.

By providing a tuple as the value to sort on for each entry, we can provide additional information on how to sort items where the first element is the same.

You cannot simply use reverse here as that'd reverse the whole list after sorting forward, and it doesn't offer the option to reverse sub-groups. The negation trick simply provides integers in the other direction from zero, which also causes the sort order to reverse. When the first element matches the sort continues to use the second element in the same forward direction.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Fantastic!! Where can I get some documentation about it, to learn how it works actually – rkatkam Feb 17 '15 at 15:50
  • @rkatkam: this is just tricking the lexicographic sort used for sequences. Let me see what I can find. – Martijn Pieters Feb 17 '15 at 15:51
  • 1
    @rkatkam: written a bit more about the tricks used. There is also the [*Sorting HowTo*](https://docs.python.org/2/howto/sorting.html) and the [Python wiki page on sorting](https://wiki.python.org/moin/HowTo/Sorting). – Martijn Pieters Feb 17 '15 at 16:02