How to Sort a List of Tuples by the Second Element in Python

To sort a list of tuples by the second element in Python, pass a key function to sorted() or list.sort(): sorted(data, key=lambda t: t[1]). Add reverse=True for descending order, or use operator.itemgetter(1), which does the same thing slightly faster. This guide shows the basic sort, sorting by the second element and then another element, mixed ascending/descending order, strings, None values and dictionary items.

All examples were run with Python 3.12.5 in the Windows Command Prompt. Reference: the official Python Sorting HOW TO.

Sort by the second element

scores = [("Anna", 91), ("Ben", 78), ("Chen", 85), ("Dev", 91)]

by_score = sorted(scores, key=lambda item: item[1])      # sort by the second element
print(by_score)

scores.sort(key=lambda item: item[1], reverse=True)      # in place, highest first
print(scores)

Output:

[('Ben', 78), ('Chen', 85), ('Anna', 91), ('Dev', 91)]
[('Anna', 91), ('Dev', 91), ('Chen', 85), ('Ben', 78)]
Command Prompt output of a list of name and score tuples sorted by the second element with sorted and a lambda key, then in descending order with sort
sorted() returns a new list; list.sort() changes the list in place.

The key function receives each tuple and returns what to compare, here the item at index 1. Tuples with equal scores (Anna and Dev, 91) keep their original order.

Using operator.itemgetter

from operator import itemgetter

cities = [("Chicago", 2.7), ("Houston", 2.3), ("Phoenix", 1.6), ("Boston", 0.65)]

print(sorted(cities, key=itemgetter(1)))                  # same as key=lambda c: c[1]
print(sorted(cities, key=itemgetter(1), reverse=True))    # descending

Output:

[('Boston', 0.65), ('Phoenix', 1.6), ('Houston', 2.3), ('Chicago', 2.7)]
[('Chicago', 2.7), ('Houston', 2.3), ('Phoenix', 1.6), ('Boston', 0.65)]

itemgetter(1) is a ready-made function equivalent to lambda t: t[1]. itemgetter(1, 0) returns a tuple of both items, which sorts by the second element and then the first.

Sort by the second element, then another element

Return a tuple from the key. Tuples compare element by element, so the second key only decides when the first is equal. To make one key descending, negate it when it is a number:

orders = [("B-12", 3, "Anna"), ("A-07", 1, "Ben"), ("C-30", 3, "Cara"), ("D-02", 1, "Ali")]

# by the second element, then by the third
print(sorted(orders, key=lambda o: (o[1], o[2])))

# second element descending, third ascending: negate the number
print(sorted(orders, key=lambda o: (-o[1], o[2])))

Output:

[('D-02', 1, 'Ali'), ('A-07', 1, 'Ben'), ('B-12', 3, 'Anna'), ('C-30', 3, 'Cara')]
[('B-12', 3, 'Anna'), ('C-30', 3, 'Cara'), ('D-02', 1, 'Ali'), ('A-07', 1, 'Ben')]
Command Prompt output sorting order tuples by the second element and then the third, and by the second element descending with a negated key
Ascending by quantity then name, and descending by quantity then name.

Sorting is stable

tasks = [("write report", 2), ("email Sam", 1), ("fix bug", 2), ("lunch", 1), ("deploy", 3)]

by_priority = sorted(tasks, key=lambda t: t[1])
print(by_priority)
# items with the same priority keep their original order (sorting is stable):
# "email Sam" before "lunch", "write report" before "fix bug"

Output:

[('email Sam', 1), ('lunch', 1), ('write report', 2), ('fix bug', 2), ('deploy', 3)]

Python’s sort keeps equal items in their original order, so you can also sort in two passes: first by the secondary key, then by the main key.

Strings, case and None values

products = [("pen", "blue"), ("mug", "Red"), ("cap", "green"), ("bag", "Black")]

print(sorted(products, key=lambda p: p[1]))                  # uppercase sorts before lowercase
print(sorted(products, key=lambda p: p[1].casefold()))       # case-insensitive

rows = [("a", 3), ("b", None), ("c", 1)]
try:
    sorted(rows, key=lambda r: r[1])
except TypeError as e:
    print("TypeError:", e)
print(sorted(rows, key=lambda r: (r[1] is None, r[1] or 0)))   # None values last

Output:

[('bag', 'Black'), ('mug', 'Red'), ('pen', 'blue'), ('cap', 'green')]
[('bag', 'Black'), ('pen', 'blue'), ('cap', 'green'), ('mug', 'Red')]
TypeError: '<' not supported between instances of 'NoneType' and 'int'
[('c', 1), ('a', 3), ('b', None)]
Command Prompt output showing uppercase-first sorting, case-insensitive sorting with casefold and a TypeError when comparing None with int, fixed by sorting None last
Case-insensitive keys and a safe key for None values.

Sort dictionary items by value

dict.items() gives (key, value) tuples, so sorting by the second element sorts a dictionary by its values:

stock = {"apples": 42, "pears": 7, "plums": 19}

print(sorted(stock.items(), key=lambda kv: kv[1]))       # items() gives (key, value) tuples
print(dict(sorted(stock.items(), key=lambda kv: kv[1], reverse=True)))

Output:

[('pears', 7), ('plums', 19), ('apples', 42)]
{'apples': 42, 'plums': 19, 'pears': 7}

For more ways to sort dictionaries, see sort a dictionary in Python.

lambda or itemgetter: which is faster?

import random
import timeit
from operator import itemgetter

data = [(i, random.random()) for i in range(200_000)]

t_lambda = min(timeit.repeat(lambda: sorted(data, key=lambda t: t[1]), number=5, repeat=3))
t_getter = min(timeit.repeat(lambda: sorted(data, key=itemgetter(1)), number=5, repeat=3))
print(f"key=lambda t: t[1] : {t_lambda / 5 * 1000:.0f} ms per sort")
print(f"key=itemgetter(1)  : {t_getter / 5 * 1000:.0f} ms per sort")

Output (one run; timings vary):

key=lambda t: t[1] : 46 ms per sort
key=itemgetter(1)  : 42 ms per sort
Command Prompt timing comparison of sorting 200,000 tuples with a lambda key and with operator.itemgetter
itemgetter is usually a little faster, but both are fine for everyday lists.

More Python sorting and list tutorials:

Frequently asked questions

How do I sort a list of tuples by the second element in Python?

sorted(data, key=lambda t: t[1]) returns a new sorted list; data.sort(key=lambda t: t[1]) sorts in place.

How do I sort by the second element in descending order?

Add reverse=True: sorted(data, key=lambda t: t[1], reverse=True).

How do I sort by the second element and then the first?

Return a tuple from the key: key=lambda t: (t[1], t[0]), or use itemgetter(1, 0).

What is the difference between sorted() and sort()?

sorted() works on any iterable and returns a new list. list.sort() changes the list in place and returns None.

How do I sort a tuple of tuples?

Tuples cannot be changed, so use sorted() and convert back if needed: tuple(sorted(tt, key=lambda t: t[1])).

Why do I get TypeError: ‘<' not supported between instances of 'NoneType' and 'int'?

Some second elements are None. Use a key that puts them first or last, for example key=lambda t: (t[1] is None, t[1] or 0).