sort one list using the values from another list

Alex Martelli aleaxit at yahoo.com
Sun Feb 26 11:33:43 EST 2006


Brian Blais <bblais at bryant.edu> wrote:

> Hello,
> 
> I have two lists, one with strings (filenames, actually), and one with a
> real-number rank, like:
> 
> A=['hello','there','this','that']
> B=[3,4,2,5]
> 
> I'd like to sort list A using the values from B, so the result would be in
> this example,
> 
> A=['this','hello','there','that']
> 
> The sort method on lists does in-place sorting.  Is there a way to do what
> I want here?

Sure, many ways, mostly ones based on the "Decorate-Sort-Undecorate"
idiom and its incarnation as the key= optional argument to function
sorted and list method sort.  I believe that a more explicit DSU is
ideal (clearer, though maybe a tad slower) in your case:

_aux = zip(B, A)
_aux.sort()
A[:] = [a for b, a in _aux]

Twisting things to use the speedy key= approach seems more "contorted"
and less general in this case, and it also needs an auxiliary structure
(to avoid slowing things down by repeated .index calls) However, things
may be different if you need to consider the possibility that B has some
duplicate items, and deeply care for such a case NOT to result in
comparisons of items of A.  The above approach would then have to be
changed, e.g., to:

_aux = zip(B, enumerate(A))
_aux.sort()
A[:] = [a for (b, (i, a)) in _aux]

where I've also added a pair of redundant parentheses to make the
nesting structure of items of _aux more obvious.  Of course, each of
these has a variant using sorted instead of sort, and for those you
could use izip from itertools rather than built-in zip, and do
everything within one single statement, etc, etc.


Alex



More information about the Python-list mailing list