Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the proper way to write comparator as key in Python 3 for sorting?

I'm not sure how to write a comparator in Python 3 as the cmp parameter is removed. Considering the following code in Python 3, how do I rewrite the comparator using only key?

import functools

def my_cmp(x, y):
    return x*5-y*2

l = [50, 2, 1, 9]
print(sorted(l, key=functools.cmp_to_key(my_cmp)))

thanks.

like image 423
Niner Avatar asked Jun 01 '15 04:06

Niner


People also ask

How do I pass a Python comparator to sort?

To do this, you must create a Checker class that implements the Comparator interface, then write an int compare(Player a, Player b) method implementing the Comparator. compare(T o1, T o2) method. In short, when sorting in ascending order, a comparator function returns -1 if a<b , 0 if a=b , and 1 if a>b .

How do you define a comparator in Python?

A comparator function is used to sort a given data structure along with the help of the sorted() function. In Python 3, we use a key function to carry out a custom sorting process. Here, we use the functools.

How does key work in Python sort?

Key Functions sort() and sorted() have a key parameter to specify a function (or other callable) to be called on each list element prior to making comparisons. The value of the key parameter should be a function (or other callable) that takes a single argument and returns a key to use for sorting purposes.

How does key work in sort?

The key parameter takes a function as its value, which is applied to each element before sorting, so that the elements are sorted based on the output of this function.


1 Answers

This "comparison" function that you came up with is inconsistent: it should provide a definite (deterministic) order, meaning, if you change the order of the elements in the list and run sorted - you should get the same result!

In your case, the order of the elements effects the sorting:

import functools

def my_cmp(x, y):
    return x*5-y*2


l = [50, 2, 1, 9]
print(sorted(l, key=functools.cmp_to_key(my_cmp))) # [2, 1, 9, 50]

l = [50, 1, 2, 9]
print(sorted(l, key=functools.cmp_to_key(my_cmp))) # [1, 2, 9, 50]

which means that your "comparison" function is inconsistent. First provide good ordering function, then it should not be very difficult to convert it to a key function.


Regards the question that you raised in the comments, key accepts a function that takes only a single argument - and returns a "measurement" of "how big is it". The easiest example would be to compare numbers, in that case your key function can simply be: lambda x: x. For any number the lambda expression will returns itself and the comparison is now trivial!

Modifying your example:

def my_key(x):
    return x    

l = [50, 2, 1, 9]
print(sorted(l, key=my_key)) # [1, 2, 9, 50]

A shorter version of the above would be:

l = [50, 2, 1, 9]
print(sorted(l, key=lambda x: x)) # [1, 2, 9, 50]
like image 64
Nir Alfasi Avatar answered Sep 22 '22 12:09

Nir Alfasi