Chapters
Python114 chapters

CollectionsChapter 31 of 114

Sort Lists

sort in place or sorted into a new list, with a key and a direction.

Two ways to sort

sort() rearranges the list in place and returns None. sorted() leaves the original alone and hands back a new list:

Python
numbers = [3, 1, 2]

numbers.sort()
print(numbers)

original = [3, 1, 2]
print(sorted(original))
print(original)

Output

[1, 2, 3]
[1, 2, 3]
[3, 1, 2]

Reversing the direction

Python
print(sorted([3, 1, 2], reverse=True))

Output

[3, 2, 1]

Sorting strings

Text sorts by character code, so capitals come before lowercase:

Python
names = ["banana", "Apple", "cherry"]
print(sorted(names))

Output

['Apple', 'banana', 'cherry']

That is rarely what a person expects. Sort case-insensitively with a key:

Python
names = ["banana", "Apple", "cherry"]
print(sorted(names, key=str.lower))

Output

['Apple', 'banana', 'cherry']

The key function

key takes a function called once per item. The list is sorted by what it returns, and the items themselves are what you get back:

Python
names = ["Katherine", "Ada", "Grace"]
print(sorted(names, key=len))

Output

['Ada', 'Grace', 'Katherine']

Sorting records by a field is the everyday use:

Python
people = [("Ada", 36), ("Grace", 45), ("Katherine", 28)]
print(sorted(people, key=lambda person: person[1]))

Output

[('Katherine', 28), ('Ada', 36), ('Grace', 45)]

operator.itemgetter does the same thing with less punctuation:

Python
from operator import itemgetter
people = [("Ada", 36), ("Grace", 45)]
print(sorted(people, key=itemgetter(1), reverse=True))

Output

[('Grace', 45), ('Ada', 36)]

Sorting by two things

Return a tuple from the key. It compares the first item, then the second when the first ties:

Python
people = [("Ada", 36), ("Zoe", 36), ("Grace", 45)]
print(sorted(people, key=lambda p: (p[1], p[0])))

Output

[('Ada', 36), ('Zoe', 36), ('Grace', 45)]

Sorting is stable

Items that compare equal keep their original order. That means you can sort twice to get a two-level ordering, least important first:

Python
from operator import itemgetter

people = [("Zoe", 36), ("Ada", 36), ("Grace", 45)]
by_name = sorted(people, key=itemgetter(0))
by_age = sorted(by_name, key=itemgetter(1))
print(by_age)

Output

[('Ada', 36), ('Zoe', 36), ('Grace', 45)]

Mixed types will not sort

Python
try:
    print(sorted([1, "two", 3]))
except TypeError as problem:
    print("TypeError:", problem)

Output

TypeError: '<' not supported between instances of 'str' and 'int'

Give a key that makes them comparable, or do not mix them.

Test yourself

3 questions

What does numbers.sort() return?

Show the answer

None — sort() rearranges in place. sorted() is the one that hands back a new list.

How do you sort names ignoring case?

Show the answer

sorted(names, key=str.lower) — The key is called once per item and decides the ordering; you still get the original items back.

What does it mean that Python's sort is stable?

Show the answer

Items that compare equal keep their original order — It means you can sort twice for a two-level ordering, least important first.

Next chapter

Copy Lists

Why assignment does not copy, and the difference between shallow and deep.