How to Use Lambda With the .sort() Method
In this lesson, you’ll see how to use a lambda for the key of the .sort()
method of lists. The .sort()
method has two parameters. key
is None
by default. reverse
is False
by default.
You won’t be altering reverse
, but you will be looking at key
because you can use a lambda expression to alter the behavior of .sort()
. When you use lambda
, you can extend key
to be much more versatile.
00:00
Lambda functions with .sort()
, filter()
, map()
, and reduce()
. In this section, you’re going to see lambda functions being used in conjunction with methods and functions. Firstly, you’ll see it being used for the key of the .sort()
method of list
, then to create the filter to filter iterables with filter()
, a function being applied to all the elements of an iterable using map()
, and the function being applied cumulatively to all the elements of an iterable using reduce()
.
00:34
Firstly, the .sort()
method of list
. As you can see from the definition here, .sort()
has two parameters: key
, which is None
by default, and reverse
, which is False
by default.
00:48
We will not be altering reverse
, but we will be looking at key
as we can use a lambda expression to alter the behavior of .sort()
.
00:59
The .sort()
method sorts the list in place using only less than (<
) or greater than (>
) comparisons between items.
01:07
Lambda functions allow us to extend key
to become much more versatile. Here’s a quick example below. We have a list of names
. We use a lambda expression to split the names
and then sort by the surname, which is the last element of the list.
01:26
Now let’s see that code in action. Here you can see a list of names
—in this case, Command Module Pilots in the Apollo program. And if we sort it, it will be sorted as you’d expect, in alphabetical order starting with the first letter. So let’s see that in action.
01:50
And you can see, we start out with 'Michael Collins'
being first in the list. And after it’s sorted, 'Alfred Worden'
is first in the list, 'Stuart Roosa'
is last in the list.
02:02
What if we wanted to sort it by surname? Well, what we need to do is to use a lambda expression to split each entry up into separate elements, and then pass this to .sort()
.
02:15
That’s fairly easy to do with a lambda expression. So again, we pass key
a lambda expression. Again I’ll choose x
—it could be any letter. And we’re going to going to go x.split()
and that will split each entry up into separate words.
02:34
And then we want to send it the last one, which is indexed with -1
. Now we’re passing the surname of each of these astronauts to .sort()
, and it will sort them by that. Let’s see that in action.
02:51
And now you can see they’re sorted by order—'Collins'
, 'Evans'
, and so on, all the way up to 'Worden'
.
03:03
So by default, this list of people
will be sorted by the first entry alphabetically. It’d be sorted by name, so it would be this character which is taken into account first, et cetera.
03:17 Now, just as an aside, I’ve done this as a list of tuples with curved brackets purely so you can see this more easily—how they are differentiated. If you have a list of lists, it would work exactly the same way, but it’s a little harder to make it out onscreen, and it’s important that you can see what’s going on and not be confused about what you’re seeing.
03:39
If you apply the .sort()
method,
03:46
that will sort them by their first name, in this case. We’re going to print out the list before, and then print out the list afterwards. And let’s see that run. So here you can see that .sort()
has sorted this original list in alphabetical order of that first entry.
04:14
So, here’s our sorted version, and you can see it’s 'Gerald'
, then 'Jo'
, 'Karen'
, and 'Steve'
—so just alphabetical order. But that is not what we want to do, so now going back to the code.
04:26
.sort()
takes the argument key
, and here we can put in the lambda expression, lambda x
in this case, and then you’re going to set x
to be the second element of each item on the list.
04:44
So this would be here, because the second element is there. Of course, it’s zero-indexed. So running this code now gives the result we’re looking for. You can see it’s sorted by age—28
, 35
, 58
, and 72
.
05:11
Lambda expressions can be used to obtain properties of objects for sorting as well. We’re going to have a small example here. Firstly, a class called Person
will be set up, which takes a name
and an age
.
05:36
And the dunder method .__repr__()
is also going to be defined to allow us to see these objects more clearly.
05:54 Now we can create some instances of the class
06:07 and then put them in a list.
06:15 We can print that list and then try to sort it. And once we’ve tried to sort it, we can print it out again. Let’s see that running. Ah. You can see we have a problem. And once you think about it, it makes sense.
06:39
There’s no way for .sort()
to know what it should sort on, as these objects aren’t something it understands. We need to allow it to do that by using a lambda function.
06:51
Here we’ll put in the parameter key
, pass it a lambda function, which in this case is going to be the .age
of each of our people.
07:09
we can see they’re now sorted by .age
. We could just as easily do it using their .name
.
Darren Jones RP Team on July 21, 2020
The [-1] gives the last element of a list (in this case the surnames as the names were split with .split(), so that the last element of that list would be the surname). You could use [1], but that would only work if each name given had only two elements - firstname, lastname. if anyone had a middle name, then it wouldn’t work correctly.
Zach Thomas on Sept. 26, 2021
When you have the key be lambda x, the function list.sort(key) automatically feeds each element in the list to the lambda function rather than the list itself?
Bartosz Zaczyński RP Team on Sept. 27, 2021
@Zach Thomas Not exactly. Both the sorted()
function and the .sort()
method accept an optional key
parameter, which lets you define the order of your elements. By default, they’re sorted by value, which produces different results depending on their type:
>>> sorted([42, 177, 13])
[13, 42, 177]
>>> sorted(["42", "177", "13"])
['13', '177', '42']
For example, numbers are sorted using total order, while strings are sorted in lexicographic order. You can override this default behavior by providing a custom callable, whether it’s a lambda expression or a fully-fledged function, to define your key. This callable will receive a single element from the list:
>>> fruits = ["watermelon", "fig", "plum", "apple", "orange"]
>>> sorted(fruits, key=len) # Sort by string length
['fig', 'plum', 'apple', 'orange', 'watermelon']
Python uses the key to know how to compare two elements and decide which one should go first. That is especially helpful with custom data types, which might contain more than one attribute to sort by:
>>> from collections import namedtuple
>>> Person = namedtuple("Person", "first_name last_name age")
>>> people = [
... Person("Joe", "Doe", 42),
... Person("John", "Smith", 27),
... Person("Anna", "Smith", 31),
... ]
>>> sorted(people, key=lambda x: x.age)
[
Person(first_name='John', last_name='Smith', age=27),
Person(first_name='Anna', last_name='Smith', age=31),
Person(first_name='Joe', last_name='Doe', age=42)
]
You can use attrgetter
to conveniently grab that attribute:
>>> from operator import attrgetter
>>> sorted(people, key=attrgetter("age"))
[
Person(first_name='John', last_name='Smith', age=27),
Person(first_name='Anna', last_name='Smith', age=31),
Person(first_name='Joe', last_name='Doe', age=42)
]
P Moz on March 6, 2023
It looks like you’re incorrectly using __repr__
when you should be using __str__
Bartosz Zaczyński RP Team on March 6, 2023
@P Moz There’s no one “correct” way to implement str()
/repr()
in your classes. The reason why Darren has implemented .__repr__()
instead of .__str__()
is because of how Python lists represent their items by default. In particuar, when you print a Python list to the console, it’ll print each item using the .__repr__()
method of each item:
>>> class Person:
... def __init__(self, name):
... self.name = name
...
... def __str__(self):
... return self.name
...
>>> people = [
... Person("Alice"),
... Person("Bob"),
... Person("John"),
... ]
>>>
>>> people
[
<__main__.Person object at 0x7f8aecc4f910>,
<__main__.Person object at 0x7f8aecc4dc10>,
<__main__.Person object at 0x7f8aecc4f650>
]
Even though the Person
class provides a .__str__()
method, the people
list still prints the default .__repr__()
representation of each item.
P Moz on March 6, 2023
I see, thanks for the information. I understand what you mean, but just in case anyone is browsing this discussion and wanted to learn a bit more, according to official documentation, __str__
should be used to create the easy-to-read string representation of an object (source), while __repr__
should be used to create an unambiguous or “official” string of the object that’s a valid Python expression and could be used to recreate the object with the same value, if possible (source).
Become a Member to join the conversation.
Justin Richie on July 21, 2020
At 1:25 in this video, what is the [-1] doing here?