Sorting
Python provides two built-in functions for sorting:
list.sort(): modifies the list in-placesorted(): builds a new sorted list from an iterable
Difference between these methods:
list.sort()method is only defined for lists. In contrast, thesorted()function accepts any iterable.list.sort()modifies the list in-place and returnsNone.sorted()returns a new sorted list. Usuallysort()is less convenient thansorted().
Sorting Basics
A simple ascending sort is very easy: just call the sorted() function. It returns a new sorted list.
Example
>>> a = [5, 2, 1, 3, 4]
>>> b = sorted(a)
>>> a # the original list is not affected
[5, 2, 1, 3, 4]
>>> b
[1, 2, 3, 4, 5]
Key
Both list.sort() and sorted() have a key parameter.
The value of the key parameter should be a function (or other callable) that serves as a key for the sort comparison. In other word, key decides the comparison criteria for sorting.
One way to specify key is to use the lambda function.
Example:
students_dict = [
{"name": "John", "age": 12, "grade": "A"},
{"name": "Mary", "age": 14, "grade": "B"},
{"name": "Ben", "age": 13, "grade": "A"}
]
sorted(students_dict, key=lambda student: student.get("age")) # sort by age
Output:
[{'age': 12, 'grade': 'A', 'name': 'John'},
{'age': 13, 'grade': 'A', 'name': 'Ben'},
{'age': 14, 'grade': 'B', 'name': 'Mary'}]
This also works for objects with named attributes.
Example:
class Student:
def __init__(self, name, age, grade):
self.name = name
self.age = age
self.grade = grade
def __repr__(self):
return repr((self.name, self.age, self.grade))
students = [
Student("John", 12, "A"),
Student("Mary", 14, "B"),
Student("Ben", 13, "A")
]
sorted(students, key=lambda student: student.age)
Output:
[('John', 12, 'A'), ('Ben', 13, 'A'), ('Mary', 14, 'B')]
Operator Module Functions
Python operator module provides convenience functions to make accessor functions easier and faster:
itemgetter()attrgetter()methodcaller()
itemgetter()
Example:
students_tuple = [
("John", 12, "A"),
("Mary", 14, "B"),
("Ben", 13, "A")
]
sorted(students_tuple, key=itemgetter(1))
Output:
[('John', 12, 'A'), ('Ben', 13, 'A'), ('Mary', 14, 'B')]
students_dict = [
{"name": "John", "age": 12, "grade": "A"},
{"name": "Mary", "age": 14, "grade": "B"},
{"name": "Ben", "age": 13, "grade": "A"}
]
sorted(students_dict, key=itemgetter("age"))
Output:
[{'age': 12, 'grade': 'A', 'name': 'John'},
{'age': 13, 'grade': 'A', 'name': 'Ben'},
{'age': 14, 'grade': 'B', 'name': 'Mary'}]
attrgetter()
Example:
class Student:
def __init__(self, name, age, grade):
self.name = name
self.age = age
self.grade = grade
def __repr__(self):
return repr((self.name, self.age, self.grade))
students = [
Student("John", 12, "A"),
Student("Mary", 14, "B"),
Student("Ben", 13, "A")
]
[('John', 12, 'A'), ('Ben', 13, 'A'), ('Mary', 14, 'B')]
order
Both list.sort() and sorted() accept a reverse parameter with a boolean value. This is used to flag descending sorts" reverse=False and reverse=True represent ascending and descening order, respectively.
Advance
Multiple levels of sorting
Multiple level of sorting can be easily achieved with operator module functions.
For example, to sort by grade then by age:
>>> sorted(students_tuple, key=itemgetter(2, 1))
[('John', 12, 'A'), ('Ben', 13, 'A'), ('Mary', 14, 'B')]
>>> sorted(students, key=attrgetter("grade", "age"))
[('John', 12, 'A'), ('Ben', 13, 'A'), ('Mary', 14, 'B')]
>>> sorted(students_dict, key=itemgetter("grade", "age"))
[{'age': 12, 'grade': 'A', 'name': 'John'},
{'age': 13, 'grade': 'A', 'name': 'Ben'},
{'age': 14, 'grade': 'B', 'name': 'Mary'}]