Skip to content

How to Sort a List of Tuples by Second or Multiple Elements in Python

Learn how to sort Python lists of tuples by the second element or multiple criteria using sorted() with lambda or itemgetter, including ascending/descending order and in-place sorting.

Lists containing tuples are a common way to structure related data in Python. Often, you need to sort this list based on the value of a specific element within each tuple (like the second element) or based on multiple elements acting as primary and secondary sort keys. Python's sorted() function and list.sort() method provide powerful ways to achieve this using the key argument.

This guide demonstrates how to sort lists of tuples by the second element or multiple elements, in both ascending and descending order.

Sorting Fundamentals: The key Argument

Both the built-in sorted() function (which returns a new sorted list) and the list.sort() method (which sorts the list in-place) accept an optional key argument.

  • key: This argument takes a function. This function is called on each element of the list before comparisons are made. The return value of this key function is then used as the basis for the sorting comparison.

This allows you to sort based on criteria other than the default element-by-element comparison of the tuples.

Sort by the Second Element (Index 1)

To sort based solely on the value at index 1 (the second element) of each tuple.

Using sorted() with lambda (Ascending)

Provide a lambda function to the key argument that extracts the element at index 1 from each tuple.

data = [('Apple', 50), ('Banana', 20), ('Cherry', 30), ('Date', 20)]

sorted_data = sorted(data, key=lambda tup: tup[1])

print(f"Original: {data}")

print(f"Sorted by 2nd element (Asc): {sorted_data}")

Output:

Original: [('Apple', 50), ('Banana', 20), ('Cherry', 30), ('Date', 20)]
Sorted by 2nd element (Asc): [('Banana', 20), ('Date', 20), ('Cherry', 30), ('Apple', 50)]
  • lambda tup: tup[1]: This anonymous function takes a tuple tup and returns its second element (tup[1]). sorted() uses these returned values (20, 20, 30, 50) for comparison.

Using sorted() with lambda (Descending)

To sort in descending order (largest to smallest based on the key), add the reverse=True argument.

data = [('Apple', 50), ('Banana', 20), ('Cherry', 30), ('Date', 20)]

sorted_data_desc = sorted(data, key=lambda tup: tup[1], reverse=True)

print(f"Original: {data}")

print(f"Sorted by 2nd element (Desc): {sorted_data_desc}")

Output:

Original: [('Apple', 50), ('Banana', 20), ('Cherry', 30), ('Date', 20)]
Sorted by 2nd element (Desc): [('Apple', 50), ('Cherry', 30), ('Banana', 20), ('Date', 20)]

Using sorted() with operator.itemgetter

The operator.itemgetter function provides a slightly more efficient way to create the key function for accessing elements by index.

from operator import itemgetter # Required import

data = [('Apple', 50), ('Banana', 20), ('Cherry', 30), ('Date', 20)]

sorted_data_itemgetter = sorted(data, key=itemgetter(1))
print(f"Sorted by 2nd element (itemgetter Asc): {sorted_data_itemgetter}")

sorted_data_itemgetter_desc = sorted(data, key=itemgetter(1), reverse=True)
print(f"Sorted by 2nd element (itemgetter Desc): {sorted_data_itemgetter_desc}")

Output:

Sorted by 2nd element (itemgetter Asc): [('Banana', 20), ('Date', 20), ('Cherry', 30), ('Apple', 50)]
Sorted by 2nd element (itemgetter Desc): [('Apple', 50), ('Cherry', 30), ('Banana', 20), ('Date', 20)]
  • key=itemgetter(1): Creates a callable that directly fetches the element at index 1. Often preferred for simple index-based keys over lambda.

Sort by Multiple Elements (Primary, Secondary Keys, etc.)

To sort based on multiple criteria (e.g., sort by the second element, and for ties, sort by the third element), have the key function return a tuple of the values you want to sort by, in the desired order of priority. Python compares tuples element by element.

Using sorted() with lambda Returning a Tuple (Ascending)

The lambda function should return a tuple like (primary_key_element, secondary_key_element, ...).

data = [(1, 'A', 100), (2, 'B', 50), (3, 'A', 75), (4, 'C', 50), (5, 'B', 60)]

sorted_multi = sorted(data, key=lambda tup: (tup[1], tup[2]))

print(f"Original: {data}")
print(f"Sorted by Cat (1), then Val (2): {sorted_multi}")

Output:

Original: [(1, 'A', 100), (2, 'B', 50), (3, 'A', 75), (4, 'C', 50), (5, 'B', 60)]
Sorted by Cat (1), then Val (2): [(3, 'A', 75), (1, 'A', 100), (2, 'B', 50), (5, 'B', 60), (4, 'C', 50)]
  • key=lambda tup: (tup[1], tup[2]): Returns tuples like ('A', 75), ('A', 100), ('B', 50), etc.
  • Python compares these tuples: ('A', 75) comes before ('A', 100) because 75 < 100. ('A', ...) comes before ('B', ...) because 'A' < 'B'.

Using sorted() with lambda Returning a Tuple (Descending)

Use reverse=True to reverse the overall sort order based on the tuple comparison.

data = [(1, 'A', 100), (2, 'B', 50), (3, 'A', 75), (4, 'C', 50), (5, 'B', 60)]

sorted_multi_desc = sorted(data, key=lambda tup: (tup[1], tup[2]), reverse=True)

print(f"Original: {data}")
print(f"Sorted by Cat (1), then Val (2) DESC: {sorted_multi_desc}")

Output:

Original: [(1, 'A', 100), (2, 'B', 50), (3, 'A', 75), (4, 'C', 50), (5, 'B', 60)]
Sorted by Cat (1), then Val (2) DESC: [(4, 'C', 50), (5, 'B', 60), (2, 'B', 50), (1, 'A', 100), (3, 'A', 75)]

Using sorted() with operator.itemgetter

itemgetter can also fetch multiple indices, returning them as a tuple, making it suitable for multi-key sorting.

from operator import itemgetter # Required import

data = [(1, 'A', 100), (2, 'B', 50), (3, 'A', 75), (4, 'C', 50), (5, 'B', 60)]

sorted_multi_itemgetter = sorted(data, key=itemgetter(1, 2))
print(f"Sorted by Cat (1), then Val (2) (itemgetter): {sorted_multi_itemgetter}")

sorted_multi_itemgetter_desc = sorted(data, key=itemgetter(1, 2), reverse=True)
print(f"Sorted by Cat (1), then Val (2) (itemgetter Desc): {sorted_multi_itemgetter_desc}")

Output:

Sorted by Cat (1), then Val (2) (itemgetter): [(3, 'A', 75), (1, 'A', 100), (2, 'B', 50), (5, 'B', 60), (4, 'C', 50)]
Sorted by Cat (1), then Val (2) (itemgetter Desc): [(4, 'C', 50), (5, 'B', 60), (2, 'B', 50), (1, 'A', 100), (3, 'A', 75)]
  • key=itemgetter(1, 2): Creates a callable that fetches elements at index 1 and 2, returning them as a tuple (element_at_1, element_at_2).

In-Place Sorting using list.sort()

If you want to modify the original list directly instead of creating a new sorted list, use the list.sort() method. It accepts the same key and reverse arguments.

from operator import itemgetter

data_to_sort = [(1, 'A', 100), (2, 'B', 50), (3, 'A', 75)]
print(f"Original list (before sort): {data_to_sort}")

data_to_sort.sort(key=itemgetter(1, 2)) # No return value needed, list is modified

print(f"Original list (after sort): {data_to_sort}")

Output:

Original list (before sort): [(1, 'A', 100), (2, 'B', 50), (3, 'A', 75)]
Original list (after sort): [(3, 'A', 75), (1, 'A', 100), (2, 'B', 50)]
  • list.sort() modifies the list directly and returns None.

Choosing Between sorted() and list.sort()

  • Use sorted(my_list, ...) when you want to keep the original list unchanged and get a new sorted list.
  • Use my_list.sort(...) when you want to modify the original list in-place and don't need to preserve the original order (this can be slightly more memory efficient as it doesn't create a new list).

Conclusion

Python's sorting functions are highly flexible for lists of tuples thanks to the key argument:

  • To sort by the second element (index 1), use key=lambda t: t[1] or key=operator.itemgetter(1).
  • To sort by multiple elements (e.g., index 1 then index 2), use key=lambda t: (t[1], t[2]) or key=operator.itemgetter(1, 2). The key function should return a tuple representing the sort priority.
  • Use reverse=True with either sorted() or list.sort() for descending order based on the key.
  • Choose sorted() to get a new list or list.sort() to modify the list in-place.

Leveraging the key argument provides precise control over how lists of tuples are ordered based on their internal elements.

Navigation