How to sort 2 elementary rowset in mixed order Using a key parameter (not cmp)

In Python, I have something like the following (although shuffled randomly):

l = [('a', 'x'),
     ('a', 'y'),
     ('a', 'z'),
     ('b', 'x'),
     ('b', 'y'),
     ('b', 'z'),
    ]

If I call sorted(l), I get a sorted result (e.g. above), which is to be expected. However, I need to forward sorting by the first element of the tuple and reverse sorting by the second element. In other words, I would like to get the following result:

l = [('a', 'z'),
     ('a', 'y'),
     ('a', 'x'),
     ('b', 'z'),
     ('b', 'y'),
     ('b', 'x'),
    ]

Python2.x has a parameter cmpthat can be passed in sorted()to achieve this result, but Python3 no longer has this. It has only a parameter key. Is there a way to achieve the desired sort order using only a parameter key?

, - functools.cmp_to_key ( ), . ?

edit: , [. (basestring, datetime)].

+5
5

Python Python 2.2.

, second reverse:

>>> from operator import itemgetter
>>> l.sort(key=itemgetter(1), reverse=True)
>>> l
[('a', 'z'), ('b', 'z'), ('a', 'y'), ('b', 'y'), ('a', 'x'), ('b', 'x')]

first:

>>> l.sort(key=itemgetter(0))
>>> l
[('a', 'z'), ('a', 'y'), ('a', 'x'), ('b', 'z'), ('b', 'y'), ('b', 'x')]
+11

:

>>> l.sort(key=lambda t: (t[0], -ord(t[1])))
>>> l
[('a', 'z'), ('a', 'y'), ('a', 'x'), ('b', 'z'), ('b', 'y'), ('b', 'x')]

, , , . , . , , ord.

+2

The Python Sorting HOWTO recommends using sort stability and sort in two passes:

>>> l.sort(key=lambda t: t[1], reverse=True)   # SECONDARY KEY: field 1 descending
>>> l.sort(key=lambda t: t[0])                 # PRIMARY KEY:   field 0 ascending
>>> l
[('a', 'z'), ('a', 'y'), ('a', 'x'), ('b', 'z'), ('b', 'y'), ('b', 'x')]
+1
source

You can do this by sorting twice in the list, first using reverse sorting with the second item in each tuple, then using regular sorting in a new sorted list with the first item in each tuple.

l = [('a', 'y'),
     ('a', 'x'),
     ('b', 'y'),
     ('b', 'x'),
     ('b', 'z'),
     ('a', 'z'),
    ]
l = sorted(l, key=lambda tup: tup[1], reverse=True)
l = sorted(l, key=lambda tup: tup[0])

Or if you prefer:

l = sorted(sorted(l, key=lambda tup: tup[1], reverse=True),
           key=lambda tup: tup[0])
+1
source
l = [('a', 'x'),
 ('a', 'y'),
 ('a', 'z'),
 ('b', 'x'),
 ('b', 'y'),
 ('b', 'z'),
]

>>> sorted(l, key = lambda x: 2*abs(ord(x[0])-ord('a')) + abs(ord(x[1])-ord('z')

Hope this helps

0
source

All Articles