Replacing cmp with key for sorting

bearophileHUGS at lycos.com bearophileHUGS at lycos.com
Mon Nov 3 13:21:27 EST 2008


On Nov 3, 6:49 pm, George Sakkis <george.sak... at gmail.com> wrote:
> I want to sort sequences of strings lexicographically but those with
> longer prefix should come earlier, e.g. for s = ['a', 'bc', 'bd',
> 'bcb', 'ba', 'ab'], the sorted sequence is ['ab', 'a', 'ba', 'bcb',
> 'bc', 'bd']. Currently I do it with:
>
> s.sort(cmp=lambda x,y: 0 if x==y else
>                                     -1 if x.startswith(y) else
>                                     +1 if y.startswith(x) else
>                                     cmp(x,y))
>
> Can this be done with an equivalent key function instead of cmp ?
>
> George

Your input and output:

s = ['a', 'bc', 'bd', 'bcb', 'ba', 'ab']
r = ['ab', 'a', 'ba', 'bcb', 'bc', 'bd']

To me your lambda looks like an abuse of the inline if expression. So
I suggest to replace it with a true function, that is more readable:

def mycmp(x, y):
    if x == y:
        return 0
    elif x.startswith(y):
        return -1
    elif y.startswith(x):
        return +1
    else:
        return cmp(x, y)

print sorted(s, cmp=mycmp)

It's a peculiar cmp function, I'm thinking still in what situations it
can be useful.

To use the key argument given a cmp function I use the simple code
written by Hettinger:

def cmp2key(mycmp):
    "Converts a cmp= function into a key= function"
    class K:
        def __init__(self, obj, *args):
            self.obj = obj
        def __cmp__(self, other):
            return mycmp(self.obj, other.obj)
    return K
print sorted(s, key=cmp2key(mycmp))

Now I'll look for simpler solutions...

Bye,
bearophile



More information about the Python-list mailing list