Python’s Key Functions for Sorting

Today we’re going to talk about one of the most underrated features of this beautiful language: key functions for sorting.

To kick things off, what exactly key functions are and how they work.In Python, when you call the sorted() function with a list as an argument, it returns a new list containing all of the elements from the original list in sorted order. But sometimes, we want to sort based on something other than just plain old alphabetical or numerical order. That’s where key functions come in!

A key function is simply a function that takes one argument and returns some value for each element in our list. When we pass this key function as an optional second argument to the sorted() function, it tells Python how to sort based on the values returned by the key function instead of just using the original elements themselves. Let’s take a look at an example:

# Define a list of fruits
fruits = ['banana', 'apple', 'orange']

# Use the sorted() function to sort the list based on the length of each element
# The key argument specifies a function to be called on each element before sorting
# In this case, we use the built-in len() function to get the length of each element
sorted_by_length = sorted(fruits, key=len)

# Print the sorted list
print(sorted_by_length)

# Output: ['orange', 'apple', 'banana']

# The sorted list is now in ascending order based on the length of each element
# This is because the key function returns the length of each element, which is used for sorting instead of the original elements themselves

In this example, we’re using the len() function as our key function. This tells Python to sort based on the length of each fruit name instead of just alphabetical order. Pretty cool, right? But what if you want to sort in reverse order based on some criteria other than numerical value or length? That’s where the reverse argument comes in!

# Define a list of fruits
fruits = ['banana', 'apple', 'orange']

# Use the sorted() function to sort the list based on the length of each fruit name
# The key argument specifies the function to be used for sorting, in this case, the len() function
# The reverse argument is set to True to sort the list in reverse order
sorted_by_length_reverse = sorted(fruits, key=len, reverse=True)

# Print the sorted list
print(sorted_by_length_reverse)

# Output: ['banana', 'orange', 'apple']

In this example, we’re using the same len() function as our key function but adding the reverse argument to sort in descending order based on length. Pretty handy! But what if you want to sort based on some more complex criteria? That’s where lambda functions come in!

A lambda function is a small anonymous function that can be used inline wherever a regular function would normally go. Let’s take a look at an example:

# Creating a list of dictionaries with people's names and ages
people = [{'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 30}, {'name': 'Charlie', 'age': 19}]

# Sorting the list of dictionaries by age, using a lambda function as the key
sorted_by_age = sorted(people, key=lambda x: x['age'])

# Printing the sorted list
print(sorted_by_age)

# Output: [{'name': 'Bob', 'age': 30}, {'name': 'Charlie', 'age': 19}, {'name': 'Alice', 'age': 25}]

# Explanation:
# The script creates a list of dictionaries with people's names and ages.
# The sorted() function is used to sort the list based on the 'age' key in each dictionary.
# The key parameter takes in a function, in this case a lambda function, which specifies the criteria for sorting.
# The lambda function takes in a parameter 'x' and returns the value of the 'age' key in the dictionary 'x'.
# This allows the sorted() function to compare the ages of each dictionary and sort them in ascending order.
# The sorted list is then printed, showing the dictionaries in order from youngest to oldest.

In this example, we’re using a lambda function as our key function to sort based on age. The syntax might look a little weird at first, but it basically means “for each element in the list (x), return x[‘age’]”. Pretty cool! But what if you want to sort based on some more complex criteria that involves multiple steps? That’s where nested lambda functions come in!

# The following script is used to sort a list of dictionaries based on a complex criteria involving multiple steps.

# First, we define a list of dictionaries called "people" with each dictionary containing a person's name and score.
people = [{'name': 'Alice', 'score': 95}, {'name': 'Bob', 'score': 80}, {'name': 'Charlie', 'score': 75}]

# Next, we use the sorted() function to sort the list "people" based on a key, which is a lambda function.
# The lambda function takes in an element from the list (x) and returns x['score'].
# This means that the list will be sorted based on the value of the 'score' key in each dictionary.
sorted_by_score = sorted(people, key=lambda x: x['score'])

# However, we want to sort the list based on a more complex criteria that involves multiple steps.
# To do this, we use nested lambda functions.
# The first lambda function takes in an element from the list (x) and returns the result of the following calculation:
# (x['score'] - the minimum score in the list) divided by (the maximum score in the list - the minimum score in the list).
# This will give us a percentile value for each person's score.
# The second lambda function then uses this percentile value as the key for sorting the list.
sorted_by_percentile = sorted(people, key=lambda x: (x['score'] - min([y['score'] for y in people])) / (max([y['score'] for y in people]) - min([y['score'] for y in people])))

# Finally, we print the sorted list.
print(sorted_by_percentile)

# Output: [{'name': 'Charlie', 'score': 75}, {'name': 'Bob', 'score': 80}, {'name': 'Alice', 'score': 95}]
# The list is now sorted in ascending order based on the percentile value of each person's score.

In this example, we’re using a nested lambda function to sort based on percentile. The outer lambda function calculates the difference between each person’s score and the minimum score in the list. The inner lambda function calculates the range of scores by finding the maximum and minimum values in the list. This gives us a normalized value for each person that we can use as our key function to sort based on percentile!

They allow us to sort based on complex criteria using lambda functions and nested lambda functions. Whether you’re working with lists of fruit names or complex datasets, key functions can help you get the job done quickly and efficiently.

SICORPS