Custom Python List Sorting

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?

3

6 Answers

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.

1

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.

8

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)
2

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)
1

I know many have already posted some good answers. However I want to suggest one nice and easy method without importing any library.

l = [(2, 3), (3, 4), (2, 4)]
l.sort(key = lambda x: (-x[0], -x[1]) )
print(l)
l.sort(key = lambda x: (x[0], -x[1]) )
print(l)

Output will be

[(3, 4), (2, 4), (2, 3)]
[(2, 4), (2, 3), (3, 4)]

The output will be sorted based on the order of the parameters we provided in the tuple format

1

Even better:

student_tuples = [
    ('john', 'A', 15),
    ('jane', 'B', 12),
    ('dave', 'B', 10),
]

sorted(student_tuples, key=lambda student: student[2])   # sort by age
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

Taken from:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Elena Rostova

Elena Rostova

Lead Health, Wellness & Medical Journalist

Elena Rostova holds a Master's degree in Public Health Journalism. She covers groundbreaking medical research, holistic wellness trends, mental health awareness, and nutritional science.

Share this article
Twitter Facebook Pinterest