[Tutor] understanding the behavious of parameter 'key' in sort

Lie Ryan lie.1296 at gmail.com
Tue Nov 24 04:30:46 CET 2009

Shashwat Anand wrote:
> I intended to sort a list which sorts according to user-defined custom 
> sorting-order.
> For example: If sorting-order is "zabc...wxy", then the output will be 
> in lexicographically sorted order but z will always be given priority 
> over rest others.
> as a test case i took sorting order as reverse of normal sorting, hence 
> i defined user_key as string.ascii_lowercase. It should sort in reverse 
> manner but I'm not getting expected output.
> (Even though it could have just been sorted as reverse=True, but my 
> intention is to generalize it for this is just a test-case). I'm not 
> able to find where the bug lies nor am i exactly sure how the key 
> function works, even though i use it in a regular fashion. Can you guys 
> help me out ?

Your code is not wrong. It's your expected output (or your need) that's 
different from a typical definition of "lexicographical sorting". In a 
typical lexicographical sorting "a" comes before "ab" since "a" is 
shorter than "ab".

So, if you want this:
> expected output: ['cba', 'cab', 'abc', 'ab', 'aa', 'a']
you must use a custom cmp= argument to reverse the shorter substring case:

like this:

import string

def my_cmp(s1, s2):
     if s1.startswith(s2):
         return -1
     elif s2.startswith(s1):
         return 1
         return cmp(s1, s2)

def userdef_sort(l, user_key):
     table = string.maketrans("".join(sorted(user_key)), user_key)
     trans = lambda x: x.translate(table)
     return sorted(l, cmp=my_cmp, key=trans)

#user_key = raw_input()
user_key = string.ascii_lowercase[::-1]
l = ['a', 'aa', 'ab', 'abc', 'cba', 'cab']

print userdef_sort(l, user_key)

More information about the Tutor mailing list