Python 3 removes the cmp
parameter to sorting functions:
builtin.sorted()
andlist.sort()
no longer accept thecmp
argument providing a comparison function. Use thekey
argument instead.
That's fine for orderings that can be determined just by inspecting a single item in the sequence (e.g. key=str.lower
). But what about custom orderings that must have two items for inspection to determine their ordering?
$ python2
Python 2.7.12+ (default, Sep 1 2016, 20:27:38)
[…]
>>> digits = ['3', '30', '34', '32', '9', '5']
>>> sorted(
... digits,
... cmp=(lambda a, b: cmp(a+b, b+a)),
... reverse=True)
['9', '5', '34', '3', '32', '30']
That two-parameter cmp
function can't be replaced with a one-parameter key
function, can it?
Use the functools.cmp_to_key
helper.
>>> import functools
>>> digits = ['3', '30', '34', '32', '9', '5']
>>> sorted(
... digits,
... key=functools.cmp_to_key(lambda a, b: cmp(a+b, b+a)),
... reverse=True)
['9', '5', '34', '3', '32', '30']
The Python 3 sorting functions take a ‘key’ parameter:
key
specifies a function of one argument that is used to extract a comparison key from each list element:key=str.lower
. The default value isNone
(compare the elements directly).
The functools.cmp_to_key
helper is designed to help you transition to
that style:
functools.cmp_to_key(func)
Transform an old-style comparison function to a key function. […] This function is primarily used as a transition tool for programs being converted from Python 2 which supported the use of comparison functions.
This works in the latest Python 2 and Python 3.
The trick is done by creating a key function that takes an item for comparison, and returns a custom object, which knows how to compare itself as specified by your comparison function.
>>> key_func = functools.cmp_to_key(lambda a, b: cmp(a+b, b+a))
>>> key_func("32")
<functools.K object at 0x7f6781ce0980>
>>> key_func("32") < key_func("5")
True
See the Sorting HOWTO for this and other tricks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With