Python sorted() Function

If you work in a data driven career, odds are you will at some point have to perform sorting on your data. Rather than writing your own sorting algorithm (which will most likely be far less efficient), Python provides a built-in function called sorted(). This function allows you to do basic sorting, such as arranging in ascending or alphabetical order, but also has the ability for a custom sort, in which you can sort according to your own specifications. 

Definition

The sorted() function takes a specified iterable input and returns a sorted list

For example:

>>> x = [4, 1, 2]
>>> sorted(x)
[1, 2, 4]

It is important to note that the sorted() function does not mutate the original list x; it creates a new list which can be stored in a separate variable.

Parameters

The sorted() function takes at most 3 arguments:

sorted(iterable, key = None, reverse = False)
  • iterable: This is the sequence to be sorted. It accepts multiple data types such as a string, list, tuple, dictionary etc. and includes nested lists. No matter which type of data is entered however, the sorted() function will always return a list.
  • key: This is an optional argument in the sorted() function with the default being None. The key parameter allows you to input a function (built-in or your own function) in order to customise how your list is sorted.
  • reverse: This is an optional argument which indicates whether the data should be sorted in ascending or descending order. The default argument is False, meaning that the data will be sorted in ascending order. 

Sorting strings

When sorting strings, the default is to organise each character in the string in ascending order and return a list of those characters.

Example 1: A single word string

>>> word = 'Python'
>>> sorted(word)
['P', 'h', 'n', 'o', 't', 'y']

Example 2: A multiple word string

>>> sentence = 'I love Python!'
>>> sorted(sentence)
[' ', ' ', '!' 'I', 'P', 'e', 'h', 'l', 'n', 'o', 'o', 't', 'v', 'y']

As can be seen in the above example, when the sorted() function is called on a string of multiple words, each character in the string is treated as an element of a list, including the empty spaces. Python orders these elements using the Unicode Standard. What the Unicode Standard does is assign a unique code to every character in all human languages. This allows Python to compare non-numeric characters on a numerical basis as each character has its assigned integer value.

If, however, you want to order a string according to the words in the string rather than according to each character, the .split() string method can be used.

Example 3: Ordering words in a sentence

>>> phrase = 'The cat in the hat'
>>> sorted(phrase.split())
['The', 'cat', 'hat', 'in', 'the']

Example 4: Ordering words in a list

>>> words = ['Book', 'Bag', 'pencil', 'basket']
>>> sorted(words)
['Bag', 'Book', 'basket', 'pencil'] 

This example better demonstrates how the Unicode Standard is used. Python orders this data by initially comparing the first letters of each word, and if it finds them to be the same, will move on to compare the second letters and then third and so on. The sorting has put the word ‘Book’ before ‘basket’ telling us that uppercase and lowercase letters do not have the same unicode code point. In general, uppercase letters will have lower code points than the lowercase counterparts, and thus, the words ‘Bag’ and ‘Book’ are placed at the beginning of the list. Since the first letter, ‘B’, is the same in both words, Python goes on to compare the second letters.

Sorting lists and other complex data types

As stated previously, when sorting data of all numeric values, the default is to sort the values in ascending order. A new list of ordered values is created which can be stored in a new variable.

Example 1: Sorting a list of numeric values

>>> values = [3, 2, 6, 5]
>>> sorted_values = sorted(values)
>>> print(sorted_values)
[2, 3, 5, 6]

Example 2: Sorting a tuple of numeric values

>>> numbers = (9, 2, 6, 3, 1)
>>> sorted_numbers = sorted(numbers)
>>> print(sorted_numbers)
[1, 2, 3, 6, 9]

Take note that, although we inserted a tuple, the sorted() function always returns a list. If desired, you can convert the sorted list into a tuple using the tuple() function and store it in a new variable:

>>> sorted_numbers_tup = tuple(sorted_numbers)
>>> print(sorted_numbers_tup)
(1, 2, 3, 6, 9)

Example 3: Sorting a dictionary

>>> d = {4: 'a', 3: 'b', 1: 'c'}
>>> sorted(d)
[1, 3, 4]

Take note that only the dictionary keys are returned in a list because, in order to return both the dictionary key and value, the key argument in the sorted() function will have to be used. This will then return a list of tuples which can be converted to a dictionary using the function dict(). The usage of keys will be covered later on in this article.

Example 4: Sorting a set

>>> s = {10, 2, 7, 3}
>>> sorted_s = sorted(s)
>>> print(sorted_s)
[2, 3, 7, 10]

Attempting to convert this ordered list into a set however, will cause you to lose the ordering because a set, by definition, is unordered.

>>> set(sorted_s)
{10, 2, 3, 7}

Example 5: Sorting a nested list

>>> a = [[2, 4], [3, 2], [1, 5], [1, 1]]
>>> sorted(a)
[[1, 1], [1, 5], [2, 4], [3, 2]]

Here, Python follows the same method as when sorting a list of words. The initial ordering compares the first elements of the nested lists. Lists with the same first element are then compared using their second elements and so on. Shorter lists are also placed before longer lists given that their initial elements are the same.

>>> b = [[1, 2, 3], [2, 4], [1, 2]]
>>> sorted(b)
[[1, 2], [1, 2, 3], [2, 4]] 

Using the key argument 

The key argument in the sorted() function is an extremely useful tool because it allows you to sort the data according to your exact specifications. The function that you input tells Python how you want your data to be ordered. Python applies that function to each element and orders the results. For this you can use one of Python’s extensive built-in functions or create your own function according to your needs.

Example 1: Using an inbuilt function, sum()

>>> marks = [[1, 4, 5], [2, 1, 2], [2, 3, 5]]
>>> sorted(marks, key = sum)
[[2, 1, 2], [1, 4, 5], [2, 3, 5]]

This example orders the nested lists by the sum of each list, smallest to largest, instead of the default to order by elements. 

Example 2: Using your own function

>>> def temp(day):
        return day[1]

>>> weather = [['Monday', 25], ['Tuesday', 21], ['Wednesday', 30]]
>>> sorted(weather, key = temp)
[['Tuesday', 21], ['Monday', 25], ['Wednesday', 30]]

This example demonstrates how you would sort a list according to the second element of each list rather than the first. We first define a function that returns the second element of each list and then use that function as our key. Of course, this is maybe not the most Pythonic way to get this result. The temp() function can be condensed into one line using lambda.

Example 3: Using lambda in the key

>>> sorted(weather, key = lambda day: day[1])
[['Tuesday', 21], ['Monday', 25], ['Wednesday', 30]]

Just these few examples demonstrate the power of the key argument. 

Using the reverse argument

The reverse argument is a fairly simple concept to understand. You use it when you want your data organised in descending instead of ascending order. It takes only a Boolean value, with True referring to descending order and False referring to ascending order. The default, of course, is False

Example: Sorting in descending order

>>> y = [2, 5, 1, 7]
>>> sorted(y, reverse = True)
[7, 5, 2, 1]

The same method is used, meaning that the first elements are compared, then the second and so on, to find the largest elements. The reverse argument can be combined with the key argument to create more complex sorts.

Trying to compare elements of different types

A limitation of the sorted() function is that it is unable to compare different data types. For example, trying to sort a list that contains both string types and int types results in a TypeError. This is fairly intuitive; how could we decide what should come first between the elements ‘apples’ and 23. 

A comparison that can be done between different types however, is comparing a numeric type (int or float) with a Boolean type. This is because the two Boolean values each have an inherent numeric value, True has the value 1 and False has the value 0. This means that we can compare lists that have numeric types as well as Boolean expressions as they will evaluate to True or False.

Example:

>>> z = [1, 'A' == 'B', 4 > 3, 0]
>>> sorted(z)
[False, 0, 1, True]

Sort stability

A helpful feature of the sorted() function is something called sort stability. What this means is that if you have an iterable with multiple elements of the same value, they will keep their original order relative to each other. This is very useful when you have two or more iterations through, for example, a list of tuples.

Example:

>>> books_read = [('Steve', 50), ('Dave', 20), ('Fiona', 37), ('Roger', 20)]
>>> sorted(books_read, key = lambda name: name[1])
[('Dave', 20), ('Roger', 20), ('Fiona', 37), ('Steve', 50)]

In this example, a list of tuples shows how many books each person read in a year. A simple lambda function was used to compare the tuples using the second value in each tuple rather than the first. You can see that Dave and Roger read the same amount of books but when the list was ordered, they kept their position relative to each other.

Difference between list.sort() and sorted() functions

As a final note, there is a similar function that exists for the sorting of lists called list.sort(). It works much the same as the sorted() function, however, there is a key difference between the two. When you call the function list.sort(), it mutates the original list that you are sorting and returns None.

>>> a = [5, 2, 6, 3]
>>> list.sort(a)
>>> a
[2, 3, 5, 6]

Therefore, when deciding which function to use, it’s important to consider whether you need to keep the original, unordered data. If there is a slight chance you will need it again, the sorted() function is a better option. Not only will it not mutate the original list, but, as mentioned previously, it will accept any iterable, making it a much more powerful function.

For interest’s sake, here is a link to the sorting algorithm used by Python: Timsort 


To boost your Python skills, download our hand-crafted Python cheat sheets and join our email academy (free):