[Tutor] custom comparator with ordered list
Peter Otten
__peter__ at web.de
Mon Jun 26 13:32:39 EDT 2017
Anish Kumar wrote:
>
>> anish singh wrote:
>>
>>> I need a custom comparator.
>>>
>>> dictionary = {a:[b,c], d:[e,f]}
>>>
>>> If both 'b' and 'e' belong to the same bin
>>> then it should be compared based on 'c' and 'f'.
>>>
>>> However, I want to also represent the result of the
>>> sorted operation in a ordered dictionary as order is
>>> important.
>>>
>>> My custom comparator is something like this:
>>>
>>>
>>> ''' x and y is a list of two elements each'''
>>> def cmpr(x, y):
>>> r = 3
>>> if x[0]//r != y[0]//r:
>>> return x[0]//r < y[0]//r
>>> return x[1] < y[1]
>>
>> This looks like it should be called less() rather than compare() as it
>> doesn't differentiate between the x < y and x == y case.
>>
>>> Please note it is not exactly comparing the first elements
>>> of the value but checking if they belong to the same bin
>>> and they do then it checks the second element as as shown
>>> above.
>>
>> The effect should be the same.
>
> Well no, take the case of [1,100] and [2,0]
> Both belong to same bin suppose then it should
> be sorted based on second index and I would
> expect [2,0] [1,100] as output.
> This is not happening currently with the original
> code I have sent.
I think that is because you do not consider all three cases.
Let's start with a function cmp() modeled after the Python 2 built-in
def cmp(a, b):
if a < b:
return -1
elif a > b:
return 1
return 0
Then your comparator could be fixed (I think) as follows
def compare(x, y):
def bin(a): return a[0] // 3
result = cmp(bin(x), bin(y))
if result:
return result
return cmp(x[1], y[1])
and that "fixed" version would be equivalent (I think) to
def compare(x, y)
def key(a): return (a[0] // 3, a[1])
return cmp((key(x), key(y))
That said, even if you use Python 2 you should use sorted() with a key
function rather than a comparison -- as shown below. Did that work for you?
>>> Example:
>>> {0:[0, 8], 1:[2, 5], 2:[2, 11], 3:[16, 17], 4:[13, 14], 5:[1, 17],
>>> {6:[17,
>>> 17] }
>>> output should be:
>>> {1:[2, 5], 0:[0, 8], 2:[2, 11], 5:[1, 17], 4:[13, 14], 3:[16, 17],
>>> {6:[17,
>>> 17] }
>>
>>>>> input = {0:[0, 8], 1:[2, 5], 2:[2, 11], 3:[16, 17], 4:[13, 14], 5:[1,
>> 17], 6:[17,
>> ... 17] }
>>>>> wanted = {1:[2, 5], 0:[0, 8], 2:[2, 11], 5:[1, 17], 4:[13, 14], 3:[16,
>> 17], 6:[17,
>> ... 17] }
>>>>> output = {k: v for k, v in sorted(input.items(), key=lambda x: (x[1]
>> [0]//3, x[1][1]))}
>>>>> assert list(output.items()) == list(wanted.items())
>>
>> As written it will work with CPython 3.6. However, for compatibility with
>> other versions of Python I recommend that you replace the plain dicts
>> above with collections.OrderedDict instances. Quoting
>>
>> https://docs.python.org/dev/whatsnew/3.6.html#whatsnew36-pep520
>>
>> """
>> The order-preserving aspect of this new [dict] implementation is
>> considered an implementation detail and should not be relied upon [...]
>> """
More information about the Tutor
mailing list