01 / 07
Left alone, it does not sort how you want
Higher-order functions and lambdas
INPUT · Slides
01 / 07
You met sorted in chapter 2 — hand it a list and a new, sorted list comes back.
But the moment you want them shortest first, that is not enough on its own. sorted puts text in alphabetical order.
names = ["Haruto", "Yui", "Minato"]print(sorted(names))Result
['Haruto', 'Minato', 'Yui']
02 / 07
sorted has a named argument called key. Hand a function to it and everything is sorted by what that function gives back.
For length that is len. Write key=len and nothing else, and you get shortest first.
names = ["Haruto", "Yui", "Minato"]print(sorted(names, key=len))Result
['Yui', 'Haruto', 'Minato']
03 / 07
Here is the thing that matters most. It is key=len, not key=len().
len() … calls the function. You would be handing over the result of the calllen … hands over the function itselfWhat sorted wants is a way of counting letters, not an answer about the length of something in particular. It is saying lend me the tool as it is; I will call it myself later.
Put the parentheses on and you get the error below.
names = ["Haruto", "Yui", "Minato"]print(sorted(names, key=len()))Result
TypeError: len() takes exactly one argument (0 given)
04 / 07
There is not always a ready-made function that fits, the way len does.
Say you want them youngest first. You want a function that takes one person and returns their age, and no such thing exists.
This is where the lambda from the last lesson earns its keep. Make it on the spot and hand it over on the spot. Far too small to be worth a name — which is precisely what lambda is for.
key=lambda p: p["age"] is "a function that takes one person p and returns p["age"]". Sort by this number, in other words.
people = [ {"name": "Yui", "age": 20}, {"name": "Haruto", "age": 15}, {"name": "Minato", "age": 18},]for person in sorted(people, key=lambda p: p["age"]): print(person["name"])Result
Haruto Minato Yui
05 / 07
reverse=True, from chapter 2, works alongside key. Just list them with a comma.
For oldest first, pull the age out with key and turn it round with reverse=True. One decides what to sort by and the other decides which way; the jobs are separate.
people = [ {"name": "Yui", "age": 20}, {"name": "Haruto", "age": 15}, {"name": "Minato", "age": 18},]for person in sorted(people, key=lambda p: p["age"], reverse=True): print(person["name"])Result
Yui Minato Haruto
06 / 07
sort, which sorts the list you already have, takes key in exactly the same way.
How you choose between them is unchanged from chapter 2. sorted if you want to keep the original, sort if you are happy for it to be sorted in place. Adding key does not affect that judgement.
names = ["Haruto", "Yui", "Minato"]names.sort(key=len)print(names)Result
['Yui', 'Haruto', 'Minato']
07 / 07
Inside, sorted is calling the function you gave it on every item one at a time. With key=len it calls len("Yui"), len("Haruto") and so on for all of them, and sorts by the numbers that come back.
So sorted is leaving part of the sorting to whoever calls it. A function that takes a function like this is called a higher-order function.
Next lesson, see the same key handed to max and min. "Find the biggest one", which took five lines in chapter 2, becomes one.