-
-
Notifications
You must be signed in to change notification settings - Fork 33.1k
Sorting techniques edits #124701
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sorting techniques edits #124701
Changes from 4 commits
ebacc5b
ff950c1
9eace43
5a344be
0102000
3363f81
5c3a312
7177968
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -47,11 +47,14 @@ lists. In contrast, the :func:`sorted` function accepts any iterable. | |||||
Key Functions | ||||||
============= | ||||||
|
||||||
Both :meth:`list.sort` and :func:`sorted` have a *key* parameter to specify a | ||||||
function (or other callable) to be called on each list element prior to making | ||||||
This :meth:`list.sort` method and the functions :func:`sorted`, | ||||||
:func:`min`, :func:`max`, :func:`heapq.nsmallest`, and | ||||||
:func:`heapq.nlargest` have a *key* parameter to specify a function (or | ||||||
other callable) to be called on each list element prior to making | ||||||
comparisons. | ||||||
|
||||||
For example, here's a case-insensitive string comparison: | ||||||
For example, here's a case-insensitive string comparison using | ||||||
:meth:`str.casefold`: | ||||||
|
||||||
.. doctest:: | ||||||
|
||||||
|
@@ -272,6 +275,71 @@ to make it usable as a key function:: | |||||
|
||||||
sorted(words, key=cmp_to_key(strcoll)) # locale-aware sort order | ||||||
|
||||||
Strategies For Unorderable Types and Values | ||||||
=========================================== | ||||||
|
||||||
A number of type and value issues can arise when sorting. | ||||||
Here are some strategies that can help: | ||||||
|
||||||
* Convert non-comparable input types to strings prior to sorting: | ||||||
|
||||||
.. doctest:: | ||||||
|
||||||
>>> data = ['twelve', '11', 10] | ||||||
>>> sorted(map(str, data)) | ||||||
['10', '11', 'twelve'] | ||||||
|
||||||
This is needed because most cross-type comparisons raise a | ||||||
:exc:`TypeError`. | ||||||
|
||||||
* Remove special values prior to sorting: | ||||||
|
||||||
.. doctest:: | ||||||
|
||||||
>>> from math import isnan | ||||||
>>> from itertools import filterfalse | ||||||
>>> data = [3.3, float('nan'), 1.1, 2.2] | ||||||
>>> sorted(filterfalse(isnan, data)) | ||||||
[1.1, 2.2, 3.3] | ||||||
|
||||||
This is needed because the `IEEE-754 standard | ||||||
<https://en.wikipedia.org/wiki/IEEE_754>`_ specifies that, "Every NaN | ||||||
shall compare unordered with everything, including itself." | ||||||
|
||||||
Likewise, ``None`` can be stripped from datasets as well: | ||||||
|
||||||
.. doctest:: | ||||||
|
||||||
>>> data = [3.3, None, 1.1, 2.2] | ||||||
>>> sorted(x for x in data if x is not None) | ||||||
[1.1, 2.2, 3.3] | ||||||
|
||||||
This is needed because ``None`` is not comparable to other types. | ||||||
|
||||||
* Convert mapping types into sorted item lists before sorting: | ||||||
|
||||||
.. doctest:: | ||||||
|
||||||
>>> from operator import methodcaller | ||||||
>>> data = [{'a': 1}, {'b': 2}] | ||||||
>>> list(map(dict, sorted(map(methodcaller('items'), data)))) | ||||||
|
>>> list(map(dict, sorted(map(methodcaller('items'), data)))) | |
>>> sorted(data, key=methodcaller('items')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this works. IIRC, an items-view implements set-like comparisons which are a subset/superset tests instead of a total ordering. Also, the intent here was to sort the key/value pairs to so that dicts that compare equal regardless of key ordering will appear side-by-side in the output.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does work here, but it does rely on the set operations and will not work for all dicts. However, that is also true for your version:
>>> data = [{'a': 1}, {'b': 2}, {'a': 3}]
>>> list(map(dict, sorted(map(methodcaller('items'), data))))
[{'a': 1}, {'b': 2}, {'a': 3}]
>>> sorted(data, key=methodcaller('items'))
[{'a': 1}, {'b': 2}, {'a': 3}]
To work correctly, we need to sort the itemsviews:
>>> sorted(data, key=lambda d: sorted(d.items()))
[{'a': 1}, {'a': 3}, {'b': 2}]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense.
Uh oh!
There was an error while loading. Please reload this page.