Combined natural and unnatural list sorting

Thorsten Kampe thorsten at thorstenkampe.de
Wed Jun 16 23:31:50 CEST 2004


* Derek Basch (2004-06-15 23:38 +0100)
> Hello All,
> 
> I need to sort a list using an unnatural sequence.
> 
> I have a list like so:
> 
> foo = ["White/M", "White/L", "White/XL", "White/S", "Black/S", "Black/M"]
> 
> print foo.sort()
> 
> ['White/L', 'White/M', 'White/S', 'White/XL', 'Black/M', 'Black/S']
> 
> The order that I actually need is:
> 
> ["White/S","White/M", "White/L", "White/XL", "Black/S", "Black/M"]
> 
> So, in other words, I need the colors sorted alphabetically and the the sizes
> sorted logically.
> 
> I looked for a while at using comparison functions with sort but I don't think
> that will work. Anyone been down this road? Suggestions?

You need some kind of general "function sort" (either using the
"Decorate, Sort, Undecorate" or the "pass a function" idiom):

def funcsort(seq, function, modus = 'dsu'):
    """
    sort seq by function(item)
    """

    if   modus == 'dsu':
        seq = [(function(item), index, item) for index, item in enumerate(seq)]
        seq.sort()
        return [item[2] for item in seq]
    elif modus == 'pass':
        seq = seq[:]
        seq.sort(lambda x, y: cmp(function(x), function(y)))
        return seq

This is a common kind of sort problem so you will need this "function
sort" anyway in near future.

Then your problem simply translates to find a function that generates
your sort items like you want them sorted (in this case something like
'White/M' -> ('White', 2) ):

SIZE_MAP = {'S':  1,
            'M':  2,
            'L':  3,
            'XL': 4}
        
def func(item):
    splititem = item.split('/')
    return splititem[0], SIZE_MAP[splititem[1]]

print funcsort(foo, func)


Thorsten



More information about the Python-list mailing list