Let’s say you have a list of tuples in Python:
tuple_list = [(1, 1, 5), (0, 1, 3), (0, 2, 4), (1, 3, 4)]
You can sort this list with the built-in sorted()
function:
sorted(tuple_list)
# Expected result
# [(0, 1, 3), (0, 2, 4), (1, 1, 5), (1, 3, 4)]
The output of this call is the same list with tuples sorted by the first element with ties broken by subsequent elements in the tuples. This works as-is because Python has a way to compare two tuples: it simply evaluates each element one at a time until it finds a difference. This means that the expression (0, 1, 3) > (0, 1, 2)
evaluates to true.
You can also sort the list in-place:
# This returns None, but tuple_list will now be sorted
tuple_list.sort()
sorted()
and sort()
both accept key
and reverse
keyword arguments that can be used to modify the default behavior.
key
The key
argument lets you specify a custom sort order. It accepts a function that takes an element and returns the value you want to compare. So if you want to sort by the second element you can do the following:
from operator import itemgetter
sorted(tuple_list, key=itemgetter(1))
# Expected result
# [(0, 1, 3), (1, 1, 5), (0, 2, 4), (1, 3, 4)]
You will often see people use something like lambda x: x[1]
instead of itemgetter()
. This approach is good to be aware of because you can use it if the items in your list are arbitrary objects. But itemgetter()
is a little faster when you just need to access indices. Another cool thing about itemgetter()
is that you can pass in multiple arguments:
sorted(tuple_list, key=itemgetter(2, 1))
# Expected result
# [(0, 1, 3), (0, 2, 4), (1, 3, 4), (1, 1, 5)]
This will sort the list by the third element, using the second element to break ties. You can prove it to yourself by calling the function on a tuple directly:
itemgetter(2, 1)((0, 2, 4))
# Expected result
# (4, 2)
reverse
You can also sort your list in descending order by passing in reverse=True
:
sorted(tuple_list, reverse=True)
# Expected result
# [(1, 3, 4), (1, 1, 5), (0, 2, 4), (0, 1, 3)]
Finally, say you want to sort by:
- The second element, ascending
- The third element, descending
You can accomplish this by sorting twice in reverse priority order:
sorted(sorted(tuple_list, key=itemgetter(2), reverse=True), key=itemgetter(1))
# Expected result
# [(1, 1, 5), (0, 1, 3), (0, 2, 4), (1, 3, 4)]
This works because TimSort (which Python uses under the hood) is stable, meaning the order of the non-sorting indices won’t be changed if you don’t explicitly sort on them.