Sorting and Itemgetter
Winter 2025
1
Adrian Salguero
Announcements
2
sorted vs. sort
3
sorted vs. sort example
hamlet = "to be or not to be that is the question whether tis nobler in the mind to suffer".split()
print("hamlet:", hamlet)
print("sorted(hamlet):", sorted(hamlet))
print("hamlet:", hamlet)
print("hamlet.sort():", hamlet.sort())
print("hamlet:", hamlet)
4
Modifies the list in place, returns None
Returns a new sorted list (does not modify the original list)
Customizing the sort order
Suppose we have a list of names and our goal is to sort them by last name
names = ["Isaac Newton", "Albert Einstein", "Niels Bohr", "Marie Curie", "Charles Darwin", "Louis Pasteur", "Galileo Galilei", "Margaret Mead"]
The following does not work, why?
When sorting, how should we be comparing these names?
5
print("sorted(names):", sorted(names))
Sort key
fruits = ["watermelon", "fig", "apple"]
print(sorted(fruits)) # alphabetical sort
print(sorted(fruits, key = len)) # sort using length (shortest to longest)
# What if we added a capital version of Watermelon?
# What if we wanted the longest to shortest sorting?
6
Using sort key to sort by last name
*This function only works on two-word names. Does not consider all possible types of names
def last_name(name):
return name.split(" ")[1]
print('last_name("Isaac Newton"):', last_name("Isaac Newton"))
7
Using sort key to sort by last name
def last_name(name):
return name.split(" ")[1]
names = ["Isaac Newton", "Ada Lovelace", "Fig Newton", "Grace Hopper"]
print(sorted(names, key=last_name))
print(sorted(names, key=len))
def last_name_len(name):
return len(last_name(name))
print(sorted(names, key=last_name_len))
8
If there is a tie in last names, preserves original order of values.
itemgetter is a function
that returns a function
Useful for creating a function that will return particular elements from a sequence (e.g., list, string, tuple)
import operator
operator.itemgetter(2)([7, 3, 8]) # 8
operator.itemgetter(0)([7, 3, 8]) # 7
operator.itemgetter(1)([7, 3, 8]) # 3
operator.itemgetter(0, 1)([7, 3, 8]) # (7, 3)
operator.itemgetter(3)([7, 3, 8]) # IndexError: list index out of range
Read the Documentation: https://docs.python.org/3/library/operator.html
9
Returns a function
Call function passing in this list as an argument
A tuple
itemgetter Exercise
import operator
lst1 = [2, 7, 3, 9, 4]
print(operator.itemgetter(1)(lst1))
print(operator.itemgetter(1, 2)(lst1))
print(operator.itemgetter(2, 3)(lst1))
tup2 = operator.itemgetter(3, 2, 1, 0)(lst1)
print(tup2)
print(operator.itemgetter(0)(tup2))
get_second = operator.itemgetter(1)
print(get_second(tup2))
print(operator.itemgetter(2)("howdy"))
print(operator.itemgetter(2, 0, 1)("howdy"))
10
Two ways to import itemgetter
import operator
student_score = ('Robert', 8)
operator.itemgetter(0)(student_score) ⇒ “Robert”
operator.itemgetter(1)(student_score) ⇒ 8
Or
from operator import itemgetter
student_score = ('Robert', 8)
itemgetter(0)(student_score) ⇒ “Robert”
itemgetter(1)(student_score) ⇒ 8
11
A tuple
Another way to import, allows you to call itemgetter directly.
Using itemgetter
from operator import itemgetter
student_score = ('Robert', 8)
itemgetter(0)(student_score) ⇒ “Robert”
itemgetter(1)(student_score) ⇒ 8
student_scores = [('Robert', 8), ('Alice', 9), ('Tina', 7)]
#Sort the list by name:
sorted(student_scores, key=itemgetter(0))
#Sort the list by score
sorted(student_scores, key=itemgetter(1))
12
Another way to import, allows you to call itemgetter directly.
What would sorted(student_scores) return?
Sorting based on two criteria
Goal: sort based on score, if there is a tie within score, sort by name
Two approaches:
student_scores = [('Robert', 8), ('Alice', 9),
('Tina', 10), ('James', 8)]
#Approach #1:
sorted_by_name = sorted(student_scores, key=itemgetter(0))
sorted_by_score = sorted(sorted_by_name, key=itemgetter(1))
#Approach #2:
sorted(student_scores, key=itemgetter(1,0))
13
Sort on most important criteria LAST
from operator import itemgetter
student_scores = [('Robert', 8), ('Alice', 9), ('Tina', 10), ('James', 8)]
sorted_by_name = sorted(student_scores, key=itemgetter(0))
>>> sorted_by_name
[('Alice', 9), ('James', 8), ('Robert', 8), ('Tina', 10)]
sorted_by_score = sorted(sorted_by_name, key=itemgetter(1))
>>> sorted_by_score
[('James', 8), ('Robert', 8), ('Alice', 9), ('Tina', 10)]
14
More sorting based on two criteria
If you want to sort different criteria in different directions, you must use multiple calls to sort or sorted
student_scores = [('Robert', 8), ('Alice', 9), ('Tina', 10), ('James', 8)]
Goal: sort score from highest to lowest; if there is a tie within score, sort by name alphabetically (= lowest to highest)
sorted_by_name = sorted(student_scores, key=itemgetter(0))
sorted_by_hi_score = sorted(sorted_by_name, key=itemgetter(1), reverse=True)
15
Remember: Sort on most important criteria LAST
Sorting Exercise
from operator import itemgetter
student_scores = [('Ann', 7), ('Raul', 6), ('Ted', 4), ('Lisa', 6)]
print(sorted(student_scores, key=itemgetter(1)))
lst_a = sorted(student_scores, key=itemgetter(0))
print(lst_a)
lst_b = sorted(lst_a, key=itemgetter(1))
print(lst_b)
lst_c = sorted(lst_a, key=itemgetter(1), reverse=True)
print(lst_c)
16