Python Sorting
1Python Sorting: overview
Sorting puts items in order: sorted() returns a new sorted list and leaves the original alone, list.sort() rearranges the list in place and returns None, and the key= function decides what Python compares.
Before this lesson: Python Lists, Python Functions
2Python Sorting: diagram
3Python Sorting: explained step by step
Sorting means putting items in order: scores from high to low, names from A to Z, tasks from most to least urgent. Python gives you two tools for it, and the difference between them causes more confusion than the sorting itself.
sorted() builds a new list
sorted() accepts any collection and returns a new list with the items in order. The original is not touched, so it is safe to use anywhere.
scores = [72, 95, 88, 61]
ranked = sorted(scores)
print(ranked)
print(scores)Because it accepts any iterable, sorted() also works on tuples, sets, strings and dictionary keys. The result is always a list: sorted("python") gives a list of single letters, not a string.
list.sort() changes the list itself
my_list.sort() rearranges the list in place and returns None. It does not build a second list, but only lists have it and the old order is gone for good.
scores = [72, 95, 88, 61]
result = scores.sort()
print(scores)
print(result)A good rule: use .sort() on a list you own and no longer need in the old order, and use sorted() when you must keep the original or when the data is not a list. Never write scores = scores.sort(), because that replaces your list with None.
Descending order, and why reversed() is different
Pass reverse=True to either tool to get the largest value first. Do not confuse it with reversed(), which does no comparing at all: it just walks the items backwards from whatever order they are already in, and gives you an iterator to wrap in list().
scores = [72, 95, 88, 61]
print(sorted(scores, reverse=True))
print(list(reversed(scores)))Strings: capital letters and numbers written as text
Text is compared one character at a time using each character's code. Every capital letter has a smaller code than every lowercase letter, so "Zoe" comes before "adam". Digits are characters too, so "10" comes before "9": Python sees that "1" is smaller than "9" and stops there.
names = ["maya", "Zoe", "adam", "Ben"]
print(sorted(names))
print(sorted(names, key=str.lower))
ids = ["10", "9", "100", "2"]
print(sorted(ids))
print(sorted(ids, key=int))Both fixes use the same tool, key=.
key=: choose what to compare
key takes a function. Python calls it once for every item, sorts by the values it returns, and then hands back the original items. The diagram above shows key=len: the words are ranked by their lengths, but you still get words.
words = ["pear", "fig", "banana", "kiwi"]
print(sorted(words, key=len))
print(sorted(words, key=lambda w: w[-1]))A lambda is a tiny function written on one line: lambda w: w[-1] means "given w, return its last letter". A normal def function works in key= just as well. Always pass the function itself (key=len), never a call (key=len()).
Sorting tuples, records and dictionaries
Tuples are compared by their first item, then by the second when the first ties. To sort by a different position, pass a key. operator.itemgetter builds a key function that picks out one position or one dictionary key, and it is shorter than a lambda.
from operator import itemgetter
orders = [("tea", 3.5), ("cake", 4.0), ("coffee", 2.5)]
print(sorted(orders))
print(sorted(orders, key=itemgetter(1)))
students = [
{"name": "Asha", "score": 82},
{"name": "Ben", "score": 91},
{"name": "Cara", "score": 77},
]
best_first = sorted(students, key=itemgetter("score"), reverse=True)
for student in best_first:
print(student["name"], student["score"])The students are dictionaries, records that store named fields as key: value pairs (the dictionary lessons come next). For objects, operator.attrgetter("score") does the same job for attributes.
A dictionary cannot be sorted in place, but you can sort its pairs and build a new dictionary, which remembers that order:
from operator import itemgetter
stock = {"apples": 12, "pears": 0, "plums": 7}
print(sorted(stock))
by_count = dict(sorted(stock.items(), key=itemgetter(1), reverse=True))
print(by_count)sorted(stock) on its own sorts the keys only; stock.items() gives you the (key, value) pairs to rank.
Sorting by several things at once
When the key function returns a tuple, Python compares the first part, and only looks at the next part if the first ones tie. A minus sign flips a number, so one part can run high to low while the other runs A to Z:
players = [("Ben", 90), ("Asha", 90), ("Cara", 75), ("Dev", 82)]
print(sorted(players, key=lambda p: (-p[1], p[0])))Highest score first, and players on the same score in alphabetical order. The minus trick only works for numbers.
Stability
Python's sort is stable: items with equal keys keep the order they had before. That makes ties predictable, and it gives you a way to mix directions on text. Sort by the less important rule first, then by the main rule:
players = [("Ben", 90), ("Asha", 90), ("Cara", 75), ("Dev", 82)]
step1 = sorted(players, key=lambda p: p[0], reverse=True)
step2 = sorted(step1, key=lambda p: p[1])
print(step2)Step 1 puts the names in Z to A order. Step 2 sorts by score, low to high, and because it is stable the two 90s stay in Z to A order.
min() and max() take key too
If you only need the best or the worst item, don't sort the whole list. min() and max() accept the same key=, and default= covers an empty collection:
from operator import itemgetter
cart = {"pen": 1.5, "lamp": 24.0, "mug": 6.0}
print(max(cart, key=cart.get))
print(min(cart.items(), key=itemgetter(1)))
print(max(["kiwi", "banana", "fig"], key=len))
print(max([], default="empty"))Items must be comparable
Sorting works by asking "is this item smaller than that one?". Numbers and text cannot answer that question for each other, so mixing them raises a TypeError. None is just as stubborn. Clean the data first, or use a key that turns every item into the same type.
mixed = [3, "2", 1]
try:
sorted(mixed)
except TypeError as err:
print(err)
print(sorted(mixed, key=int))Quick reference: Python Sorting
- Python sort() vs sorted(): What Is the Difference? — `list.sort()` sorts a list **in place** and returns `None`, while `sorted(iterable)` leaves the original unto…
- How to Sort a Dictionary by Value in Python — Use `dict(sorted(d.items(), key=lambda item: item[1]))` to sort a dictionary by value, and add `reverse=True`…
- How to Compare Strings Ignoring Case in Python — Convert both strings to the same case before comparing: `a.casefold() == b.casefold()` (or `a.lower() == b.lo…
- Python Program to Find the Largest Number in a List — The largest number in a list is `max(numbers)`. To do it by hand, start with the first item and replace it wh…
- Python Binary Search Program (Iterative and Recursive) — Binary search finds a value in a **sorted** list by repeatedly comparing the target with the middle item and …
- Python Program to Find the Second Largest Number in a List — To find the second largest number, remove duplicates, sort, and take the second from the end: `sorted(set(num…
- Python Anagram Program: Check if Two Strings Are Anagrams — Two strings are anagrams if they contain the same letters the same number of times. In Python, compare `sorte…
- Python Bubble Sort Program (with Explanation) — Bubble sort sorts a list by repeatedly comparing neighbouring items and swapping them when they are in the wr…
4Python Sorting: syntax
new_list = sorted(items) # new list, original unchanged
sorted(items, reverse=True) # largest first
my_list.sort() # in place, returns None
sorted(items, key=len) # sort by a rule
sorted(items, key=str.lower) # case-insensitive
sorted(rows, key=lambda r: (-r[1], r[0])) # several rules at once
from operator import itemgetter, attrgetter
sorted(rows, key=itemgetter("score")) # sort records by a field
sorted(d.items(), key=itemgetter(1)) # sort a dict's pairs by value
max(items, key=len, default=None) # best item by a rule
list(reversed(items)) # just flip the order
5Python Sorting: run the example
Press Run (or Ctrl + Enter). The output (step 6) appears directly below the code. Change anything and run it again.
players = [
{"name": "Maya", "score": 88},
{"name": "Ben", "score": 95},
{"name": "Asha", "score": 88},
{"name": "Dev", "score": 71},
]
ranking = sorted(players, key=lambda p: (-p["score"], p["name"]))
for place, player in enumerate(ranking, start=1):
print(place, player["name"], player["score"])
best = max(players, key=lambda p: p["score"])
worst = min(players, key=lambda p: p["score"])
print("Best:", best["name"], "| Lowest:", worst["name"])
print("Original first:", players[0]["name"])Expected output1 Ben 95
2 Asha 88
3 Maya 88
4 Dev 71
Best: Ben | Lowest: Dev
Original first: Maya
7Python Sorting: how the example works
Hover or tap a step to highlight its lines in the example above.
- Line 1-6
playersis a list of four dictionaries. Each player is one record with a"name"and a"score". - Line 8
sorted()builds a new list. The key returns the tuple(-score, name)for every player: the minus sign puts the highest score first, and the name breaks ties from A to Z. That is why Asha comes before Maya, who both scored 88. - Line 9-10
enumerate(..., start=1)hands out the place numbers 1, 2, 3, 4 while the loop walks through the sorted list and prints each player. - Line 12-13
max()andmin()use the samekey=idea: they compare the scores but return the whole dictionary of the best and the worst player, not the score itself. - Line 14
max()returned a whole dictionary, sobest["name"]reads the name from it. Ben has the highest score and Dev the lowest. - Line 15
playersstill starts with Maya.sorted()made a new list, so the original order was never touched.
8Python Sorting: common mistakes
Assigning the result of .sort()
✗ Wrong
scores = [72, 95, 88]
scores = scores.sort()
print(scores[0])✓ Right
scores = [72, 95, 88]
scores.sort()
print(scores[0]).sort() changes the list in place and returns None, so scores now holds None and the list is lost. Call .sort() on its own line, or use sorted() if you want a new list.
Sorting numbers that are stored as text
✗ Wrong
ids = ["10", "9", "100"]
print(sorted(ids))✓ Right
ids = ["10", "9", "100"]
print(sorted(ids, key=int))Strings are compared one character at a time, so "10" is smaller than "9". Tell Python to compare the numeric value with key=int; you still get the original strings back.
Mixing numbers and text in one list
✗ Wrong
readings = [18, "21", 19]
print(sorted(readings))✓ Right
readings = [18, "21", 19]
numbers = []
for item in readings:
numbers.append(int(item))
print(sorted(numbers))Python cannot decide whether "21" is smaller than 18. Convert every item to the same type before sorting. (The error may name the two types in the opposite order, depending on which pair Python compared first.)
Calling the key function instead of passing it
✗ Wrong
words = ["pear", "fig", "banana"]
print(sorted(words, key=len()))✓ Right
words = ["pear", "fig", "banana"]
print(sorted(words, key=len))key needs the function itself, so Python can call it once per item. Writing len() calls it right now, with no argument. Drop the parentheses.
Sorting a dictionary and expecting pairs or values
✗ Wrong
stock = {"apples": 12, "pears": 0, "plums": 7}
print(sorted(stock))✓ Right
stock = {"apples": 12, "pears": 0, "plums": 7}
print(sorted(stock.items(), key=lambda pair: pair[1]))Looping over a dictionary (and so sorting it) gives its keys. To rank by value, sort stock.items() and tell key to look at the second part of each pair.
9Python Sorting: exercises
Write your answer, then press Check. The checks run in your browser.
1. Leaderboard without changing the scores
Write code Easy ✓ CompletedComplete the function leaderboard(scores). It must return a new list with the scores from highest to lowest, and it must not change the list it receives (the caller may still need the original order).
def leaderboard(scores):
# return a NEW list, highest score first
pass
results = [72, 95, 88, 61]
print(leaderboard(results))
print(results)
reverse=True for largest first.def leaderboard(scores):
return sorted(scores, reverse=True)
results = [72, 95, 88, 61]
print(leaderboard(results))
print(results)
2. Predict the three orders
Predict the output Easy ✓ CompletedRead the code and type exactly what it prints, line by line. Then press Check to run it and compare.
words = ["banana", "apple", "Cherry", "Apple"]
print(sorted(words))
print(sorted(words, key=str.lower))
print(max(words, key=len))
['Apple', 'Cherry', 'apple', 'banana']
['apple', 'Apple', 'banana', 'Cherry']
banana
2 more exercises → 6 more examples
Questions learners ask
What is the difference between sort() and sorted() in Python?
sorted(items) works on any iterable and returns a new sorted list, leaving the original unchanged. my_list.sort() exists only on lists, sorts the list in place and returns None. Both accept key= and reverse=.
How do I sort a list of dictionaries by one of their keys?
Pass a key function that reads that field: sorted(rows, key=lambda r: r["score"]), or the shorter sorted(rows, key=itemgetter("score")) from the operator module. Add reverse=True for largest first, or return a tuple from the key to sort by several fields.
Why does Python sort "10" before "9" and capital letters before lowercase ones?
Strings are compared one character at a time by character code. "1" is smaller than "9", so "10" comes first, and every capital letter has a smaller code than every lowercase letter. Use key=int for numbers stored as text and key=str.lower (or str.casefold) for case-insensitive order.
Further reading
10Next lesson
Up nextPython SetsA set is an unordered collection of unique values: adding a value that is already there changes nothing, and checking w…Related:
Python ListsPython List MethodsPython DictionariesPython Lambda Functions
← Python Unpacking · All Data Structures lessons · Practise in the IDE