Welcome, guest | Sign In | My Account | Store | Cart

Here we use the properties of "cmp()" and "or" to produce a compact dialect for sorting a list.

Python, 48 lines
 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48``` ```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 name # # "cmp(X, Y)" return 'false' (0) when X and Y compare equal, # so "or" makes the next "cmp()" to be evaluated. # To reverse the sorting order, simply swap X and Y in cmp(). # # This can also be used if we have some other sorting criteria associated with # the elements of the list. We simply build an auxiliary list of tuples # to pack the sorting criteria together with the main elements, then sort and # unpack the result. # def sorting_criterium_1(data): return string.split(data)[-1] # This is again the last name. def sorting_criterium_2(data): return len(data) # This is some fancy sorting criterium. # Pack the auxiliary list: aux_list = map(lambda x: (x, sorting_criterium_1(x), sorting_criterium_2(x)), star_list) # Sort: aux_list.sort(lambda x,y: ( cmp(x[1], y[1]) or # Sort by criteria 1 (last name)... cmp(y[2], x[2]) or # ... then by criteria 2 (in reverse order) ... cmp(x, y))) # ... then by the value in the main list. # Unpack the resulting list: star_list = map(lambda x: x[0], aux_list) print "Another sorted list of stars:" for name in star_list: print name ```

#### 1 comment

Alex Martelli 21 years, 8 months ago

decorate-sort-undecorate idiom does it better. dsu variant of this (faster, clearer):

``````# "decorate" == Pack the auxiliary list:
aux_list=[(sort_crit1(x),sort_crit2(x),x) for x in star_list]
# "sort" == JUST sort, no wasted effort/complication
aux_list.sort()
# "undecorate" == Unpack the resulting list:
star_list = [x[-1] for x in aux_list]
``````

This doesn't easily do "reverse" sorting on some of the fields while being "direct" on others. On number criteria, you can just change sign (use -sort_critN(x)). On string criteria, you need a string map that swaps chr(x) with chr(255-x) for x in range(128), or wider if Unicode (but you only need to write that once).

 Created by Jose Sebrosa on Thu, 29 Mar 2001 (PSF)