@@ -18,7 +18,9 @@ Sorting Basics
18
18
==============
19
19
20
20
A simple ascending sort is very easy: just call the :func: `sorted ` function. It
21
- returns a new sorted list::
21
+ returns a new sorted list:
22
+
23
+ .. doctest ::
22
24
23
25
>>> sorted ([5 , 2 , 3 , 1 , 4 ])
24
26
[1, 2, 3, 4, 5]
@@ -28,6 +30,8 @@ in-place (and returns ``None`` to avoid confusion). Usually it's less convenient
28
30
than :func: `sorted ` - but if you don't need the original list, it's slightly
29
31
more efficient.
30
32
33
+ .. doctest ::
34
+
31
35
>>> a = [5 , 2 , 3 , 1 , 4 ]
32
36
>>> a.sort()
33
37
>>> a
@@ -36,6 +40,8 @@ more efficient.
36
40
Another difference is that the :meth: `list.sort ` method is only defined for
37
41
lists. In contrast, the :func: `sorted ` function accepts any iterable.
38
42
43
+ .. doctest ::
44
+
39
45
>>> sorted ({1 : ' D' , 2 : ' B' , 3 : ' B' , 4 : ' E' , 5 : ' A' })
40
46
[1, 2, 3, 4, 5]
41
47
@@ -48,6 +54,8 @@ comparisons.
48
54
49
55
For example, here's a case-insensitive string comparison:
50
56
57
+ .. doctest ::
58
+
51
59
>>> sorted (" This is a test string from Andrew" .split(), key = str .lower)
52
60
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
53
61
@@ -59,6 +67,8 @@ input record.
59
67
A common pattern is to sort complex objects using some of the object's indices
60
68
as keys. For example:
61
69
70
+ .. doctest ::
71
+
62
72
>>> student_tuples = [
63
73
... (' john' , ' A' , 15 ),
64
74
... (' jane' , ' B' , 12 ),
@@ -69,6 +79,8 @@ as keys. For example:
69
79
70
80
The same technique works for objects with named attributes. For example:
71
81
82
+ .. doctest ::
83
+
72
84
>>> class Student :
73
85
... def __init__ (self , name , grade , age ):
74
86
... self .name = name
@@ -95,6 +107,8 @@ convenience functions to make accessor functions easier and faster. The
95
107
96
108
Using those functions, the above examples become simpler and faster:
97
109
110
+ .. doctest ::
111
+
98
112
>>> from operator import itemgetter, attrgetter
99
113
100
114
>>> sorted (student_tuples, key = itemgetter(2 ))
@@ -106,6 +120,8 @@ Using those functions, the above examples become simpler and faster:
106
120
The operator module functions allow multiple levels of sorting. For example, to
107
121
sort by *grade * then by *age *:
108
122
123
+ .. doctest ::
124
+
109
125
>>> sorted (student_tuples, key = itemgetter(1 ,2 ))
110
126
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
111
127
@@ -119,6 +135,8 @@ Both :meth:`list.sort` and :func:`sorted` accept a *reverse* parameter with a
119
135
boolean value. This is used to flag descending sorts. For example, to get the
120
136
student data in reverse *age * order:
121
137
138
+ .. doctest ::
139
+
122
140
>>> sorted (student_tuples, key = itemgetter(2 ), reverse = True )
123
141
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
124
142
@@ -132,6 +150,8 @@ Sorts are guaranteed to be `stable
132
150
<https://en.wikipedia.org/wiki/Sorting_algorithm#Stability> `_\. That means that
133
151
when multiple records have the same key, their original order is preserved.
134
152
153
+ .. doctest ::
154
+
135
155
>>> data = [(' red' , 1 ), (' blue' , 1 ), (' red' , 2 ), (' blue' , 2 )]
136
156
>>> sorted (data, key = itemgetter(0 ))
137
157
[('blue', 1), ('blue', 2), ('red', 1), ('red', 2)]
@@ -143,13 +163,17 @@ This wonderful property lets you build complex sorts in a series of sorting
143
163
steps. For example, to sort the student data by descending *grade * and then
144
164
ascending *age *, do the *age * sort first and then sort again using *grade *:
145
165
166
+ .. doctest ::
167
+
146
168
>>> s = sorted (student_objects, key = attrgetter(' age' )) # sort on secondary key
147
169
>>> sorted (s, key = attrgetter(' grade' ), reverse = True ) # now sort on primary key, descending
148
170
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
149
171
150
172
This can be abstracted out into a wrapper function that can take a list and
151
173
tuples of field and order to sort them on multiple passes.
152
174
175
+ .. doctest ::
176
+
153
177
>>> def multisort (xs , specs ):
154
178
... for key, reverse in reversed (specs):
155
179
... xs.sort(key = attrgetter(key), reverse = reverse)
@@ -220,21 +244,27 @@ comparisons. That function should take two arguments to be compared and then
220
244
return a negative value for less-than, return zero if they are equal, or return
221
245
a positive value for greater-than. For example, we can do:
222
246
247
+ .. doctest ::
248
+
223
249
>>> def numeric_compare (x , y ):
224
250
... return x - y
225
251
>>> sorted ([5 , 2 , 4 , 1 , 3 ], cmp = numeric_compare) # doctest: +SKIP
226
252
[1, 2, 3, 4, 5]
227
253
228
254
Or you can reverse the order of comparison with:
229
255
256
+ .. doctest ::
257
+
230
258
>>> def reverse_numeric (x , y ):
231
259
... return y - x
232
260
>>> sorted ([5 , 2 , 4 , 1 , 3 ], cmp = reverse_numeric) # doctest: +SKIP
233
261
[5, 4, 3, 2, 1]
234
262
235
263
When porting code from Python 2.x to 3.x, the situation can arise when you have
236
264
the user supplying a comparison function and you need to convert that to a key
237
- function. The following wrapper makes that easy to do::
265
+ function. The following wrapper makes that easy to do:
266
+
267
+ .. testcode ::
238
268
239
269
def cmp_to_key(mycmp):
240
270
'Convert a cmp= function into a key= function'
@@ -255,6 +285,12 @@ function. The following wrapper makes that easy to do::
255
285
return mycmp(self.obj, other.obj) != 0
256
286
return K
257
287
288
+ .. doctest ::
289
+ :hide:
290
+
291
+ >>> sorted ([5 , 2 , 4 , 1 , 3 ], key = cmp_to_key(reverse_numeric))
292
+ [5, 4, 3, 2, 1]
293
+
258
294
To convert to a key function, just wrap the old comparison function:
259
295
260
296
.. testsetup ::
@@ -280,6 +316,8 @@ Odd and Ends
280
316
simulated without the parameter by using the builtin :func: `reversed ` function
281
317
twice:
282
318
319
+ .. doctest ::
320
+
283
321
>>> data = [(' red' , 1 ), (' blue' , 1 ), (' red' , 2 ), (' blue' , 2 )]
284
322
>>> standard_way = sorted (data, key = itemgetter(0 ), reverse = True )
285
323
>>> double_reversed = list (reversed (sorted (reversed (data), key = itemgetter(0 ))))
@@ -289,7 +327,9 @@ Odd and Ends
289
327
290
328
* The sort routines are guaranteed to use :meth: `__lt__ ` when making comparisons
291
329
between two objects. So, it is easy to add a standard sort order to a class by
292
- defining an :meth: `__lt__ ` method::
330
+ defining an :meth: `__lt__ ` method:
331
+
332
+ .. doctest ::
293
333
294
334
>>> Student.__lt__ = lambda self , other : self .age < other.age
295
335
>>> sorted (student_objects)
@@ -300,6 +340,8 @@ Odd and Ends
300
340
are stored in a dictionary, they can be used to sort a separate list of student
301
341
names:
302
342
343
+ .. doctest ::
344
+
303
345
>>> students = [' dave' , ' john' , ' jane' ]
304
346
>>> newgrades = {' john' : ' F' , ' jane' :' A' , ' dave' : ' C' }
305
347
>>> sorted (students, key = newgrades.__getitem__ )
0 commit comments