In Sorting a Python list by two criteria Fouad gave the following answer:
sorted(list, key=lambda x: (x[0], -x[1]))
I'd like to sort the following list primarily on the list of tuples primarily on the second item in each element in ascending order, followed by the first (alphabetic) item in descending order:
[('Ayoz', 1, 18, 7), ('Aidan', 2, 4, 9), ('Alan', 2, 4, 9), ('Arlan', 5, 6, 7), ('Luke', 15, 16, 2), ('Tariq', 5, 4, 2)]
to give the answer:
[('Ayoz', 1, 18, 7), ('Alan', 2, 4, 9), ('Aidan', 2, 4, 9), ('Tariq', 5, 4, 2), ('Arlan', 5, 6, 7), ('Luke', 15, 16, 2)]
using the above approach if possible . I tried
tlist = [('Ayoz', 1, 18, 7), ('Aidan', 2, 4, 9), ('Alan', 2, 4, 9), ('Arlan', 5, 6, 7), ('Luke', 15, 16, 2), ('Tariq', 5, 4, 2)]
sorted(tlist, key=lambda elem: (elem[1], -elem[0]))
but that only works when elem[0] is numeric (in this case it gives a TypeError: bad operand type for unary -: 'str')
I'll be grateful for any help. Python version is 3.4
The built in sorting routines in Python are stable. That is, if two items have the same key value, then they keep the order they had relative to each other (the one closer to the front of the list stays closer to the front). So you can sort on multiple keys using multiple sorting passes.
from operator import itemgetter
tlist = [('Ayoz', 1, 18, 7), ('Aidan', 2, 4, 9), ('Alan', 2, 4, 9),
('Arlan', 5, 6, 7), ('Luke', 15, 16, 2), ('Tariq', 5, 4, 2)]
# sort by name in descending order
tlist.sort(key=itemgetter(0), reverse=True)
print('pass 1:', tlist)
# sort by element 1 in ascending order. If two items have the same value
# the names stay in the same order they had (descending order)
tlist.sort(key=itemgetter(1))
print(npass 2:', tlist)
Prints:
pass 1: [('Tariq', 5, 4, 2), ('Luke', 15, 16, 2), ('Ayoz', 1, 18, 7), ('Arlan', 5, 6, 7), ('Alan', 2, 4, 9), ('Aidan', 2, 4, 9)]
pass 2: [('Ayoz', 1, 18, 7), ('Alan', 2, 4, 9), ('Aidan', 2, 4, 9), ('Tariq', 5, 4, 2), ('Arlan', 5, 6, 7), ('Luke', 15, 16, 2)]
tlist = [('Ayoz', 1, 18, 7), ('Alan', 2, 4, 9), ('Aidan', 2, 4, 9), ('Arlan', 5, 6, 7), ('Luke', 15, 16, 2), ('Tariq', 5, 4, 2)]
sorted(tlist, key=lambda elem: (elem[1],sorted(elem[0],reverse=True)))
Worked it out but it took me half an hour to type so I'm posting no matter what. I still welcome a better way of doing it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With