CommonLounge Archive

Python3: Sorting

July 26, 2018

In this tutorial, we will look at sorting lists in detail. In particular, we will cover:

  • The sorted() function
  • Custom sorting by passing key function in sorted()
  • The difference between sorted() and list.sort()

Let’s get started!

The sorted() function

The easiest way to sort is with the sorted(list) function, which takes a list and returns a new list with those elements in sorted order. The original list is not changed.

a = [5, 1, 4, 3]
print(sorted(a))  ## [1, 3, 4, 5]
print(a)  ## [5, 1, 4, 3]

It’s most common to pass a list into the sorted() function, but in fact it can take as input any sort of iterable collection. The older list.sort() method is an alternative detailed below. The sorted() function seems easier to use compared to sort(), so I recommend using sorted().

The sorted() function can be customized through optional arguments. The sorted() optional argument reverse=True, e.g. sorted(list, reverse=True), makes it sort backwards.

strs = ['aa', 'BB', 'zz', 'CC']
print(sorted(strs))  ## ['BB', 'CC', 'aa', 'zz'] (case sensitive)
print(sorted(strs, reverse=True))   ## ['zz', 'aa', 'CC', 'BB']

Custom Sorting

For more complex custom sorting, sorted() takes an optional key argument which is a function. In Python, we can pass around functions like len, str.lower etc. as arguments. This, key argument available in sorted() is a function that specifies how to transform each element before comparison.

The key function takes in 1 value and returns 1 value, and the returned “proxy” value is used for the comparisons within the sort.

For example with a list of strings, specifying key=len (the built in len() function) sorts the strings by length, from shortest to longest. The sort calls len() for each string to get the list of proxy length values, and then sorts with those proxy values.

strs = ['ccc', 'aaaa', 'd', 'bb']
print(sorted(strs, key=len))  ## ['d', 'bb', 'ccc', 'aaaa'] 

As another example, specifying str.lower as the key function is a way to force the sorting to treat uppercase and lowercase the same:

## "key" argument specifying str.lower function to use for sorting
strs = ['BB', 'zz', 'CC', 'aa']
print(sorted(strs, key=str.lower))  ## ['aa', 'BB', 'CC', 'zz']

You can also pass in your own my_function as the key function, like this:

## Say we have a list of strings we want to sort by the last letter of the string.
strs = ['xc', 'zb', 'yd' ,'wa']
## Write a little function that takes a string, and returns its last letter.
## This will be the key function (takes in 1 value, returns 1 value).
def my_function(s):
    return s[-1]
## Now pass key=my_function to sorted() to sort by the last letter:
print(sorted(strs, key=my_function))  ## ['wa', 'zb', 'xc', 'yd']

To use key= custom sorting, remember that you provide a function that takes one value and returns the proxy value to guide the sorting.

sorted() vs list.sort()

As an alternative to sorted(), the sort() method on a list sorts that list into ascending order, e.g. list.sort(). The sort() method changes the underlying list and returns None, so use it like this:

alist.sort()            ## correct
alist = blist.sort()    ## NO incorrect, sort() returns None

The above is a very common misunderstanding with sort() — it does not return the sorted list. The sort() method must be called on a list; it does not work on any enumerable collection (but the sorted() function above works on anything). The sort() method predates the sorted() function, so you will likely see it in older code. The sort() method does not need to create a new list, so it can be a little faster in the case that the elements to sort are already in a list.

Summary

This was a short tutorial, but it covered a number of very important concepts. To recap, we learned the following:

  • The sorted() function
  • Custom sorting by passing key function in sorted()
  • The difference between sorted() and list.sort()

Content was originally based on https://developers.google.com/edu/python/sorting, but has been modified since. Licensed under CC BY 3.0. Code samples licensed under the Apache 2.0 License.


© 2016-2022. All rights reserved.