Skip to content

Commit 165ed68

Browse files
authored
Sorting techniques edits (python#124701)
1 parent 02b49c5 commit 165ed68

File tree

1 file changed

+70
-3
lines changed

1 file changed

+70
-3
lines changed

Doc/howto/sorting.rst

+70-3
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,14 @@ lists. In contrast, the :func:`sorted` function accepts any iterable.
4747
Key Functions
4848
=============
4949

50-
Both :meth:`list.sort` and :func:`sorted` have a *key* parameter to specify a
51-
function (or other callable) to be called on each list element prior to making
50+
The :meth:`list.sort` method and the functions :func:`sorted`,
51+
:func:`min`, :func:`max`, :func:`heapq.nsmallest`, and
52+
:func:`heapq.nlargest` have a *key* parameter to specify a function (or
53+
other callable) to be called on each list element prior to making
5254
comparisons.
5355

54-
For example, here's a case-insensitive string comparison:
56+
For example, here's a case-insensitive string comparison using
57+
:meth:`str.casefold`:
5558

5659
.. doctest::
5760

@@ -272,6 +275,70 @@ to make it usable as a key function::
272275

273276
sorted(words, key=cmp_to_key(strcoll)) # locale-aware sort order
274277

278+
Strategies For Unorderable Types and Values
279+
===========================================
280+
281+
A number of type and value issues can arise when sorting.
282+
Here are some strategies that can help:
283+
284+
* Convert non-comparable input types to strings prior to sorting:
285+
286+
.. doctest::
287+
288+
>>> data = ['twelve', '11', 10]
289+
>>> sorted(map(str, data))
290+
['10', '11', 'twelve']
291+
292+
This is needed because most cross-type comparisons raise a
293+
:exc:`TypeError`.
294+
295+
* Remove special values prior to sorting:
296+
297+
.. doctest::
298+
299+
>>> from math import isnan
300+
>>> from itertools import filterfalse
301+
>>> data = [3.3, float('nan'), 1.1, 2.2]
302+
>>> sorted(filterfalse(isnan, data))
303+
[1.1, 2.2, 3.3]
304+
305+
This is needed because the `IEEE-754 standard
306+
<https://en.wikipedia.org/wiki/IEEE_754>`_ specifies that, "Every NaN
307+
shall compare unordered with everything, including itself."
308+
309+
Likewise, ``None`` can be stripped from datasets as well:
310+
311+
.. doctest::
312+
313+
>>> data = [3.3, None, 1.1, 2.2]
314+
>>> sorted(x for x in data if x is not None)
315+
[1.1, 2.2, 3.3]
316+
317+
This is needed because ``None`` is not comparable to other types.
318+
319+
* Convert mapping types into sorted item lists before sorting:
320+
321+
.. doctest::
322+
323+
>>> data = [{'a': 1}, {'b': 2}]
324+
>>> sorted(data, key=lambda d: sorted(d.items()))
325+
[{'a': 1}, {'b': 2}]
326+
327+
This is needed because dict-to-dict comparisons raise a
328+
:exc:`TypeError`.
329+
330+
* Convert set types into sorted lists before sorting:
331+
332+
.. doctest::
333+
334+
>>> data = [{'a', 'b', 'c'}, {'b', 'c', 'd'}]
335+
>>> sorted(map(sorted, data))
336+
[['a', 'b', 'c'], ['b', 'c', 'd']]
337+
338+
This is needed because the elements contained in set types do not have a
339+
deterministic order. For example, ``list({'a', 'b'})`` may produce
340+
either ``['a', 'b']`` or ``['b', 'a']``.
341+
275342
Odds and Ends
276343
=============
277344

0 commit comments

Comments
 (0)