Sorting by One Field, Then by Another
Credit: José Sebrosa
Problem
You need to sort a list by more than one field of each item.
Solution
Passing a comparison function to a list’s
sort method is slow for
lists of substantial size, but it can still be quite handy when you
need to sort lists that are reasonably small. In particular, it
offers a rather natural idiom to sort by more than one field:
import string
star_list = ['Elizabeth Taylor', 'Bette Davis', 'Hugh Grant', 'C. Grant']
star_list.sort(lambda x,y: (
cmp(string.split(x)[-1], string.split(y)[-1]) or # Sort by last name...
cmp(x, y))) # ...then by first name
print "Sorted list of stars:"
for name in star_list:
print nameDiscussion
This recipe uses the properties of the
cmp
built-in function and the or operator to produce a
compact idiom for sorting a list over more than one field of each
item.
cmp(X, Y) returns false (0)
when X and Y compare equal, so
only in these cases does or let the next call to
cmp happen. To reverse the sorting order, simply
swap X and Y as arguments to
cmp.
The fundamental idea of this recipe can also be used if another sorting criterion is associated with the elements of the list. We simply build an auxiliary list of tuples to pack the sorting criterion together with the main elements, then sort and unpack the result. This is more akin to the DSU idiom:
def sorting_criterion_1(data): return string.split(data)[-1] # This is again the last name def sorting_criterion_2(data): return len(data) # This is some ...