Python List Sorting
Learning outcomes:
- Simple sorting using
sort()
- Sorting in decreasing order using
reverse
- Using the
key
parameter - Sorting without mutating using
sorted()
Introduction
Sorting is an extremely common task performed on lists in Python in many applications. A website needs to sort a list of users accordingly to their name; an online shopping application might want to sort products based on their prices; a university portal might want to sort students according to their GPA; and so on.
In addition to this, some common algorithms out there that operate on lists require them to be sorted. The highly efficient binary search is a perfect example.
In Python, there are two ways to sort a list: one is using the sort()
method of lists, and the other is using the global sorted()
function. In this chapterm we shall discover both these ways in meticulous detail.
Simple sorting
The most straightforward way to sort a list is to call sort()
on it, without any arguments.
It will sort all the items of the list in increasing order, also known as ascending order, or alphabetical order.
The sort()
method, as we already know, sorts a list by side effect. That is, it doesn't return a new sorted list; rather it sorts the list in place and returns None
itself.
sort()
method mutates the list it's called on.Following we have a list of numbers that we want to print in increasing order:
nums = [4, 0, 1, 18, 6, -3, -50]
To do so, we would go on and call the sort()
method on this list and then print it:
nums = [4, 0, 1, 18, 6, -3, -50]
nums.sort()
print(nums)
Calling nums.sort()
sorts nums
in place, after which we refer back to it in order to print it.
Sorting in decreasing order
To sort a list in decreasing order, set the reverse
keyword argument to sort()
to True
.
list.sort(reverse=True)
As the name suggests, the reverse
keyword argument specifies whether to sort the list in reverse order i.e decreasing order. By default, it's False
and so the list doesn't get sorted in reverse order.
Below we sort the same list nums
above, this time in decreasing order:
nums = [4, 0, 1, 18, 6, -3, -50]
nums.sort(reverse=True)
print(nums)
Sorting with a key
Apart from reverse
, the sort()
method can be provided one more keyword argument and that is key
.
list.sort(key=None, reverse=False)
key
specifies a function to be called on each element of the list being sorted to return a value to be used for comparison in the underlying sorting algorithm.
Let's see how it works.
Suppose we have a list of students, each represented using a tuple whose first item is the stundent's name and the second item is the student's age:
students = [("Mark", 20), ("James", 19), ("Sandra", 20), ("Bill", 21)]
Now let's say we want to sort this list based on the name of each student. Calling sort()
, as is, won't work in this case since each item is a tuple, and therefore can't be validly compared with another one.
What we need to do is to tell Python what to use in comparing two items. This is where key
comes in.
students = [("Mark", 22), ("James", 19), ("Sandra", 20), ("Bill", 21)]
def get_age(student):
return student[1]
students.sort(key=get_age)
print(students)
We create a function get_age()
and pass that as key
to sort()
. Now whenever an item in the list is compared against another (in the underlying sorting algorithm), this function is called on both of them and the names of the students retrieved, respectively.
Whichever student's age is smaller than the other one's, it gets ordered first.
We can use key
to sort lists in complex ways.
An example, sorting a list of co-ordinates based on their distances from the origin, is demonstrated below:
points = [(0, 5), (3, 5), (6, 6), (0, 0), (2, 9), (4, 12)]
def distance(point):
# pythagoras's theorem
return (point[0] ** 2 + point[1] ** 2) ** 2
points.sort(key=distance)
print(points)
Given a point (represented as a tuple of two items: the x co-ordinate followed by the y co-ordinate), the function distance()
returns its distance from the origin, computed using the very famous Pythagoreon Theorem.
This function is set as the key
of points.sort()
. It's called by sort()
for each of the elements of points
, and then the comparison is made over the returned value, that is the distance of the respective point from the origin.
The point with the least amount of distance is put first, while the point with the largest distance is put last. In short, points
is sorted according to the distance of each point, in increasing order.
Here's the output:
Sorting using sorted()
Uptil this point in this chapter, we've been considering sorting examples using the sort()
method of lists. The sort()
method mutates a given list, and doesn't itself return anything.
This means that if we want to work with a sorted version of a list without modifying its original order, we have to do some additional work of copying the list.
In the code below, we ought to work with a sorted configuration of nums
, but at the same time, need its original order preserved. This is possible by first making a copy of nums
, and then sorting this copy:
nums = [8, 5, 1, 3, 0, 4, 4, 12, 19]
nums2 = nums[:]
nums2.sort()
# work with nums2
print(nums2)
The thing is that, often times, this boilerplate can become frustrating — we want to quickly work with a list's sorted version, and then forget it later on; why create another list?
This is where sorted()
comes in.
sorted(key=None, reverse=False)
The sorted()
function works exactly how sort()
does — there is no single difference in the syntax of both these methods, except for that the former doesn't mutate the original list — rather it returns a new list in a sorted configuration.
sorted()
method is meant to right away return the sorted list, be it any order, using any key.Here's a comparison of sort()
and sorted()
:
Utility | sort() method | sorted() function |
---|---|---|
List mutation | Yes | No |
Return value | None | The list |
Parameters | key and reverse | The list to sort, key and reverse |
Let's consider a quick example:
We want to print out each element in a list nums
in increasing order, without modifying its original order. Obviously, this is much convenient using sorted()
:
nums = [8, 5, 1, 3, -19]
for num in sorted(nums):
print(num)
print(nums)
1
3
5
8
[8, 5, 1, 3, -19]
The first five prints here are the elements of nums
in increasing order. Then the list nums
is printed to see whether it has been changed or not. As expected, it is untouched.
Spread the word
Think that the content was awesome? Share it with your friends!
Join the community
Can't understand something related to the content? Get help from the community.