I was refactoring some old code of mine and came across of this:
alist.sort(cmp_items)
def cmp_items(a, b):
if a.foo > b.foo:
return 1
elif a.foo == b.foo:
return 0
else:
return -1
The code works (and I wrote it some 3 years ago!) but I cannot find this thing documented anywhere in the Python docs and everybody uses sorted()
to implement custom sorting. Can someone explain why this works?
Using sort(), lamba, index(): The sort() function does the required in-place sorting(without creating a separate list to store the sorted order) along with a lambda function with a key to specify the function execution for each pair of tuples, the index() function helps to get the order from our custom list list_2.
The easiest way to sort is with the sorted(list) function, which takes a list and returns a new list with those elements in sorted order. The original list is not changed. It's most common to pass a list into the sorted() function, but in fact it can take as input any sort of iterable collection.
Summary. Use the Python List sort() method to sort a list in place. The sort() method sorts the string elements in alphabetical order and sorts the numeric elements from smallest to largest. Use the sort(reverse=True) to reverse the default sort order.
As a side note, here is a better alternative to implement the same sorting:
alist.sort(key=lambda x: x.foo)
Or alternatively:
import operator
alist.sort(key=operator.attrgetter('foo'))
Check out the Sorting How To, it is very useful.
It's documented here.
The sort() method takes optional arguments for controlling the comparisons.
cmp specifies a custom comparison function of two arguments (list items) which should return a negative, zero or positive number depending on whether the first argument is considered smaller than, equal to, or larger than the second argument: cmp=lambda x,y: cmp(x.lower(), y.lower()). The default value is None.
Just like this example. You want sort this list.
[('c', 2), ('b', 2), ('a', 3)]
output:
[('a', 3), ('b', 2), ('c', 2)]
you should sort the tuples by the second item, then the first:
def letter_cmp(a, b):
if a[1] > b[1]:
return -1
elif a[1] == b[1]:
if a[0] > b[0]:
return 1
else:
return -1
else:
return 1
Then convert it to a key function:
from functools import cmp_to_key
letter_cmp_key = cmp_to_key(letter_cmp))
Now you can use your custom sort order:
[('c', 2), ('b', 2), ('a', 3)].sort(key=letter_cmp_key)
This does not work in Python 3.
You can use functools cmp_to_key to have old-style comparison functions work though.
from functools import cmp_to_key
def cmp_items(a, b):
if a.foo > b.foo:
return 1
elif a.foo == b.foo:
return 0
else:
return -1
cmp_items_py3 = cmp_to_key(cmp_items)
alist.sort(cmp_items_py3)
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