Python: How to Sort a List?
(The Right
Way)
You have a python list and you want to sort the items it contains.
Basically, you can either use sort or sorted to achieve what you want.
The difference between sort and sorted is that sort is a list method that modifies
the list in place whereas sorted is a built-in function that creates a new list
without touching the original one.
In this article, I will teach you how to use these functions to sort, in an ascending
or descending manner, a list of numbers, strings, tuples, or literally any object.
I will also teach you how to define your own custom sort functions.
Read the whole article if you want to learn all about list sorting in Python.
Otherwise, feel free to jump straight to a specific section.
Sorting a list of numbers
Sorting a list of strings
o Sorting a list of strings in a case insensitive manner
Sorting a list of tuples
o Sorting a list of tuples by the second element
Sorting a list of objects
Sorting a List of Numbers
Sorting a numerical list is a piece of cake in Python.
You can sort a list of numbers (integers or floats) very easily by using
the sort method.
Here is an example:
>>> L = [15, 22.4, 8, 10, 3.14]
>>> L.sort()
>>> L
[3.14, 8, 10, 15, 22.4]
Notice that the list L was sorted in place. No new objects were created.
If you want to create a new sorted list without modifying the original one, you
should use the sorted function instead.
>>> L = [15, 22.4, 8, 10, 3.14]
>>> sorted_list = sorted(L)
>>> L
[15, 22.4, 8, 10, 3.14]
>>> sorted_list
[3.14, 8, 10, 15, 22.4]
As you can notice, both sort and sorted sort items in an ascending order by
default.
If you want to sort in a descending order, all you have to do is add the
parameter reverse = True to either the sort or sorted functions.
They both accept it!
Here is another example to show how you can use the sort method in a descending
manner.
>>> L = [15, 22.4, 8, 10, 3.14]
>>> L.sort(reverse = True)
>>> L
[22.4, 15, 10, 8, 3.14]
Now let’s take a look at how to sort a list of strings.
Sorting a List of Strings
So what if you want to sort a list of strings instead of numbers?
Well, nothing really changes.
You can still use sort or sorted.
Here is an example using sort:
>>> L = ["oranges", "apples", "bananas"]
>>> L.sort()
>>> L
['apples', 'bananas', 'oranges']
and you can still use the reverse parameter to sort in a descending order.
Let’s look at another example, this time using sorted
>>> L = ["oranges", "apples", "bananas"]
>>> sorted(L, reverse = True)
['oranges', 'bananas', 'apples']
So far so good, but there is a catch.
Let’s see what happens when there exists uppercase letters.
>>> L = ["oranges", "apples", "Bananas"]
>>> L.sort()
>>> L
['Bananas', 'apples', 'oranges']
That’s interesting. Bananas appears before apples
The reason for that is because Python treats all uppercase letters to be lower than
lowercase letters.
If that’s what you want then cool, go ahead and use it without any modifications.
However, most of the time you want to treat strings as case insensitive when it
comes to sorting.
So how can you sort a list of strings in a case insensitive
manner?
Starting with Python 2.4, both sort and sorted added an optional key parameter.
This key parameter specifies a function that will be called on each list item before
making comparisons.
This is indeed very helpful because now we can pass the str.lower as
the keyparameter to the sort function.
And this will instruct the sort function to perform comparisons between the all-
lowercase versions of the strings which is exactly what we want!
>>> L = ["oranges", "apples", "Bananas"]
>>> L.sort(key=str.lower)
>>> L
['apples', 'Bananas', 'oranges']
As you can see, now the sorting is case insensitive.
In fact the key parameter is very powerful as it allows us to define our own custom
sorting functions as we will see later.
Sorting a List of Tuples
Before we dive in, let’s see how Python compares two tuples.
Tuples are compared element by element starting from the first element which is
very similar to how strings are compared.
In other words, you start out by comparing the first elements of the tuples and if
they are not equal, this is the result of the comparison.
If they are equal, the second items are compared and so on.
>>> (2, 4) < (4, 1)
True
>>> (2, 4) < (2, 6)
True
If this is your goal, then just use the sort method or the sorted function and both
will work just fine.
>>> sorted([(5, 4), (3, 3), (3, 10)])
[(3, 3), (3, 10), (5, 4)]
But sometimes this is not really what you want.
For example, assume you have a list of tuples where the first element in each tuple
represents a name, and the second one represents the age.
And we want to sort this list of tuples by age.
how can you sort a list of tuples by the second element?
The key parameter will again come to the rescue.
We can define our custom sort by defining our own key function.
def custom_sort(t):
return t[1]
L = [("Alice", 25), ("Bob", 20), ("Alex", 5)]
L.sort(key=custom_sort)
print(L)
# output
# [('Alex', 5), ('Bob', 20), ('Alice', 25)]
There you go!
You can even write a neater code if you want by using lambdas.
L = [("Alice", 25), ("Bob", 20), ("Alex", 5)]
L.sort(key=lambda x: x[1])
print(L)
# output
# [('Alex', 5), ('Bob', 20), ('Alice', 25)]
Sorting a List of Objects
So what about if you have a list of generic objects and you want to sort these
objects based on some custom criteria.
The key parameter is your friend.
Let’s take an example.
Assume you have a User class that looks like this
class User:
def __init__(self, name, age):
self.name = name
self.age = age
A simple class that has name and age attributes.
Let’s create some User objects and add them to a list.
Bob = User('Bob', 20)
Alice = User('Alice', 30)
Leo = User('Leo', 15)
L = [Bob, Alice, Leo]
Now let’s say you want to sort the objects in this list alphabetically by
the name attribute.
Here is one way you can do that:
L.sort(key=lambda x: x.name)
print([item.name for item in L])
# output: ['Alice', 'Bob', 'Leo']
If you want to sort the objects based on the age attribute instead, here is what you
need to do:
L.sort(key=lambda x: x.age)
print([item.name for item in L])
# output: ['Leo', 'Bob', 'Alice']
And just like that, you can define any custom sort on any python object you can
think of.
Happy sorting! 🙂