0

During a current school project of mine, I came up with a specific sorting algorithm which I nicknamed parallel_sort. By giving it a list of integers and a list of dictionaries, it sorts the dictionaries according to the integers. For example :

parallel_sort([1,0,2],[{1:1},{0:0},{2:2}]) #[{0:0},{1:1},{2:2}]

It works perfectly fine, and I wondered if I could make it simpler by using the sort method. I first thought of using a list of (integer,dictionary) tuples, but in some cases the integers were the same, so I couldn't. So I had an idea : if I had a class that couldn't be compared to anything and put it the middle of those tuples, it could stop the tuple comparison to consider the dictionaries. The new parallel_sort would work in the following way :

def parallel_sort(int_lst,dict_lst):
    tuple_lst=[]
    for i in range(len(int_lst)):
        tuple_lst.append((int_lst[i],incomparable_class,dict_lst[i]))
    tuple_lst.sort()
    res=[]
    for tupl in tuple_lst:
        res.append(tupl[2])
    return res

Moreover, I realized that as long as the incomparable class stopped the tuple comparison, I could even put mixed types behind it, meaning I could do stuff like this :

parallel_sort([1,0,2],[0,'0',[]]) #['0',0,[]]

So I tried to make said class :

class Incomparable:
    def __init__(self): #The incomparable class itself doesn't do anything
        pass
    def __eq__(self,obj): #Never equal to anything
        return False
    def __ne__(self,obj):
        return True
    def __gt__(self,obj): #Never greater than anything
        return False
    def __ge__(self,obj):
        return False
    def __lt__(self,obj): #Never lesser than anything
        return False
    def __le__(self,obj):
        return False

I obviously did some testing, and then ran into an issue :

incmp=Incomparable()

0<incmp
#False

0>incmp
#False

0==incmp
#False

incmp==incmp
#False

incmp!=incmp
#True

(0,incmp,0)<(0,0,'0')
#True

(0,incmp,0)>(0,0,'0')
#True

#Up to here, it works as intended

(0,incmp,0)<(0,incmp,'0')
#TypeError: '>' not supported between instances of 'int' and 'str'

I tried to find out if tuple comparison had additional rules for classes, but there didn't seem to be. I knew it works based on the lexicographic order, and I thought I had successfully bypassed that with my incomparable class. Since incmp!=incmp is True, the comparison was supposed to stop.

Even by puting True and False in different ways in the incomparable class definition, it never works.

What goes wrong during the tuple comparison ? Is there some way to make the incomparable class work, or to have something that would work along the same line ?

New contributor
Gjyslaf is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

1 Answer 1

1

Your Incomparable class returns results for all comparison operations. return False doesn't mean "I can't be compared". def __gt__(self, obj): return False means Incomparable is never greater than obj. Which means it's equal or smaller.

For all practical intents and purposes, a class which always returns the same answer to any "are you greater or smaller" check behaves randomly. In this case, whatever comparison Python is asking of the class, it causes it to not be able to definitively say which tuple is greater by comparing the two Incomparables, and thus it continues to compare the third tuple indices. Which are truly incomparable.

If you want to signal to Python that a comparison operation isn't implemented, you must return NotImplemented.


But this is all way overcomplicating things anyway. What you want is a Schwartzian transform:

order = [1, 0, 2]
values = [{1: 1}, {0: 0}, {2: 2}]

result = [v for _, v in sorted(zip(order, values))]

zip creates tuples like (1, {1: 1}), sorted sorts them (by their first value), the list comprehension untangles the values again.

If your order values may not be unique and you need to make sorted not consider the values for potentially incompatible comparison, then just explicitly tell sorted what to sort by:

result = [v for _, v in sorted(zip(order, values), key=lambda i: i[0])]
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.