Using a comparator function to sort
Hire the world's top talent on demand or became one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Isolated
--
Chapters
00:00 Using A Comparator Function To Sort
00:48 Accepted Answer Score 65
01:17 Answer 2 Score 72
02:08 Answer 3 Score 5
02:25 Answer 4 Score 1
03:20 Thank you
--
Full question
https://stackoverflow.com/questions/1274...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #sorting #comparator
#avk47
ANSWER 1
Score 72
In Python 3 there is no cmp argument for the sorted function (nor for list.sort).
According to the docs, the signature is now sorted(iterable, *, key=None, reverse=False), so you have to use a key function to do a custom sort. The docs suggest:
Use
functools.cmp_to_key()to convert an old-style cmp function to a key function.
Here's an example:
>>> def compare(x, y):
...     return x[0] - y[0]
... 
>>> data = [(4, None), (3, None), (2, None), (1, None)]
>>> from functools import cmp_to_key
>>> sorted(data, key=cmp_to_key(compare))
[(1, None), (2, None), (3, None), (4, None)]
However, your function doesn't conform to the old cmp function protocol either, since it returns True or False. For your specific situation you can do:
>>> your_key = cmp_to_key(make_comparator(cmpValue))
>>> sorted(data, key=your_key)
[(1, None), (2, None), (3, None), (4, None)]
using the make_comparator function from @Fred Foo's answer.
ACCEPTED ANSWER
Score 65
You're passing the comparator as the key function. You should be passing it as the cmp, wrapped in some kind of function that turns it into a proper comparator.
def make_comparator(less_than):
    def compare(x, y):
        if less_than(x, y):
            return -1
        elif less_than(y, x):
            return 1
        else:
            return 0
    return compare
sortedDict = sorted(subjects, cmp=make_comparator(cmpValue), reverse=True)
(Although actually, you should be using key functions:
sorted(subjects, operator.itemgetter(0), reverse=True)
Also note that sortedDict will not actually be a dict, so the name is rather confusing.)
ANSWER 3
Score 5
The answer of @kaya3 is correct. I just propose another implementation in which we can use boolean for the comparator.
class YourTupleComparator(tuple):
    def __lt__(self, other):
        return self[0] < other[0]
sorted(subjects, key=YourTupleComparator)
ANSWER 4
Score 1
I don't know how does the answer of @Tuan Chau work. However, it may fail in complex situations.
Consider this comparison: each element is a tuple with two dimension. Element A is less than B if one of two conditions met: 1. A[0] is less than B[0]. 2. A[0]==B[0] and A[1]>B[0]. Therefore (1, 2) < (2, 1), (1, 2) < (1, 1).
Try the following snippets:
from functools import cmp_to_key
class Character(tuple):
    def __le__(self, other) -> bool:
        if self[0] < other[0] or (self[0] == other[0] and self[1] >= other[1]):
            return True
        return False
def compare(x, y):
    if x[0] == y[0]:
        return y[1] - x[1]
    return x[0] - y[0]
if __name__ == "__main__":
    array = [[1, 1], [2, 1], [2, 2], [1, 2]]
    print(sorted(array, key=Character))  # [[1, 1], [1, 2], [2, 1], [2, 2]]
    print(sorted(array, key=cmp_to_key(compare)))  # [[1, 2], [1, 1], [2, 2], [2, 1]]
As you can see, the result of class Character is wrong.