Cheat on Python sorting
1 Defiition/Syntax (sort vs sorted)
1.1 mylist.sort()
The list.sort()
method modifies the list in-place (and returns None to
avoid confusion.) Usually less convient than sorted, but if you don't need
the original list, it is slightly more efficient.
1.2 sorted(mylist)
Calling the sorted()
function returns a new sorted list.
sorted([5, 2, 4, 1, 3])
Returns: [1, 2, 3, 4, 5]
1.3 Modifiers.
Both mylist.sort() and sorted(mylist) can use optional key functions:
mylist.sort(reverse=True|False, key=myFunc)
Where reverse
is optional specifiys ascending (False) or descending (True)
And key=myFunc
is optional function that can specify the sorting criteria
See lambda examples below:
2 Simple Examples
movies = ["Jabberwalkie", "Life of Brian", "Holy Grail", "A Meaning of Life"] movies.sort()
3 Examples with key based sorting
This example sorts by length of string, not by alphabetical order
# A function that returns the length of the value: def myFunc(e): return len(e) actors = ['John', 'Michael', 'Eric', 'Graham', 'Terry', 'Terry'] actors.sort(key=myFunc)
3.1 Examples key based sorting using dictionary keys
>>> student_tuples = [ ('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10), ] >>> sorted(student_tuples, key=lambda student: student[2]) # sort by age [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
See the lamda.org file for details on lambda functions.
The same technique works for objects with named attributes.
# Initializing list of dictionaries knights = [{ "name" : "King Arthur", "age" : 40}, { "name" : "Sir Robin", "age" : 42 }, { "name" : "Sir Bedevere", "age" : 42 }, { "name" : "Sir Lancelot", "age" : 41 }, { "name" : "Patsy", "age" : 35 }, { "name" : "Sir Galahad", "age" : 39 }] pprint(knights) # using sorted and lambda to print list sorted # by age print("The list printed sorting by age: ") pprint(sorted(knights, key = lambda i: i['age'])) # using sorted and lambda to print list sorted # by both age and name. Notice that "Sir Bedevere" # now comes before "Sir Robin" print("The list printed sorting by age and name: ") pprint( sorted(knights, key = lambda i: (i['age'], i['name']))) # Another example with classes: >>> class Student: def __init__(self, name, grade, age): self.name = name self.grade = grade self.age = age def __repr__(self): return repr((self.name, self.grade, self.age)) >>> student_objects = [ Student('john', 'A', 15), Student('jane', 'B', 12), Student('dave', 'B', 10), ] >>> sorted(student_objects, key=lambda student: student.age) # sort by age [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
3.2 Examples of sorting a list of dictionaries according to some dictionary value
Python code snippet that uses both lamda, and sorting by key
# Initializing list of dictionaries from pprint import pprint knights = [{ "name" : "King Arthur", "age" : 40}, { "name" : "Sir Robin", "age" : 42 }, { "name" : "Sir Bedevere", "age" : 42 }, { "name" : "Sir Lancelot", "age" : 41 }, { "name" : "Patsy", "age" : 35 }, { "name" : "Sir Galahad", "age" : 39 }] pprint(knights) # using sorted and lambda to print list sorted # by age print("The list printed sorting by age: ") pprint(sorted(knights, key = lambda i: i['age'])) # using sorted and lambda to print list sorted # by both age and name. Notice that "Sir Bedevere" # now comes before "Sir Robin" print("The list printed sorting by age and name: ") pprint( sorted(knights, key = lambda i: (i['age'], i['name']))) # now in descending order print("The list printed sorting by age in descending order: " ) pprint(sorted(knights, key = lambda i: i['age'],reverse=True))
Similar technique for tuples:
>>> student_tuples = [ ('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10), ] >>> sorted(student_tuples, key=lambda student: student[2]) # sort by age [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
3.3 Examples using Python's standard library itemgetter module
3.3.1 See also ~/bin/python/bin/sort-keys-dicionary.py
Also the attrgetter module. from operator import itemgetter, attrgetter
The key-function patterns shown above are very common, so Python provides convenience functions to make accessor functions easier and faster. The operator module has itemgetter(), attrgetter(), and a methodcaller() function.
Using those functions, the above examples become simpler and faster:
>>> >>> from operator import itemgetter, attrgetter >>> >>> sorted(studenttuples, key=itemgetter(2)) [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)] >>> >>> sorted(studentobjects, key=attrgetter('age')) [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)] The operator module functions allow multiple levels of sorting. For example, to sort by grade then by age:
>>> >>> sorted(studenttuples, key=itemgetter(1,2)) [('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)] >>> >>> sorted(studentobjects, key=attrgetter('grade', 'age')) [('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]