Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 3 sorting: Custom comparer removed in favor of key - why?

In Python 2.4, you can pass a custom comparer to sort.

Let's take the list -

list=[5,1,2,3,6,0,7,1,4]

To sort with the even numbers first, and then odds, we can do the following -

evenfirst=lambda x,y:1 if x%2>y%2 else -1 if y%2>x%2 else x-y
list.sort(cmp=evenfirst)
list == [0, 2, 4, 6, 1, 1, 3, 5, 7] # True

In Python 3, you can only pass key (which is also supported in Python 2.4).

Of course, the same sorting can be achieved in Python 3 with the right key:

list.sort(key=lambda x:[x%2,x])

I am curious about the decision of not supporting custom comparers anymore, especially when it seems something that could be implemented easily enough.

Is it true that in all, or most of the cases, a desired sort order has a natural key?

In the example above for example, such a key exists - and actually the code becomes more succinct using it. Is it always the case?

(I am aware of this recipe for converting comparer to key, but ideally, one should not have to take such workarounds if it could be built into the language.)

like image 520
KalEl Avatar asked Sep 04 '13 14:09

KalEl


People also ask

Why was CMP removed from python3?

cmp was removed because the key attribute to . sort() and sorted() is superior in most cases. It was a hold-over from C more than anything, and was confusing to boot. Having to implement a separate __cmp__ method next to the rich comparison operators ( __lt__ , __gt__ , etc.)

Is sort in python stable?

sort() and sorted() in python are “stable sorts”, meaning that it'll preserve the existing order when faced with a tie.

What is__ cmp__ in python?

The __cmp__() special method is no longer honored in Python 3. In Python 2, __cmp__(self, other) implemented comparison between two objects, returning a negative value if self < other , positive if self > other , and zero if they were equal.

How do you compare functions in python?

Python - cmp() Method The cmp() is part of the python standard library which compares two integers. The result of comparison is -1 if the first integer is smaller than second and 1 if the first integer is greater than the second. If both are equal the result of cmp() is zero.


2 Answers

Performance.

The cmp function was called every time the sorting algorithm needed a comparison between two elements.

In contrast, the key object can be cached. That is, the sorting algorithm only needs to get the key once for each element and then compare the keys. It doesn't need to get a new key for every comparison.

like image 104
OdraEncoded Avatar answered Oct 20 '22 00:10

OdraEncoded


Sorting by keys is well-defined, meaning the result doesn't depend on which (stable) sorting algorithm you use. There's no pathological key function. You might suggest random.random(), but that simply shuffles the list.

Whereas sorting with a compare function is well-defined only if the function is transitive and antisymmetric, which Python can neither test nor prove. What happens if you sort by nonsense compare function lambda(x, y): 1? You can't say, the result depends on the algorithm. Some algorithms might not even terminate.

like image 6
Colonel Panic Avatar answered Oct 19 '22 23:10

Colonel Panic