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:
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
print(sorted([3, 1, 2], reverse=True))Output
[3, 2, 1]
Sorting strings
Text sorts by character code, so capitals come before lowercase:
names = ["banana", "Apple", "cherry"]
print(sorted(names))Output
['Apple', 'banana', 'cherry']
That is rarely what a person expects. Sort case-insensitively with a key:
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:
names = ["Katherine", "Ada", "Grace"]
print(sorted(names, key=len))Output
['Ada', 'Grace', 'Katherine']
Sorting records by a field is the everyday use:
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:
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:
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:
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
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 questionsWhat 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.
Copy Lists
Why assignment does not copy, and the difference between shallow and deep.