Sorting a list depending of the indexes of another sorted list
Steven D'Aprano
steve at REMOVE-THIS-cybersource.com.au
Mon Jan 21 08:58:48 EST 2008
On Mon, 21 Jan 2008 09:53:10 +0100, Peter Otten wrote:
> Santiago Romero wrote:
>
>> I'm trying to sort both lists so that they end like this:
>>
>> preferences = [10, 20, 30]
>> hosts = [ "mx1.domain.com", "mx2.domain.com", "anotherhost.domain.com"
>> ]
>>
>> I want to sort hosts list depending on the numeric order of
>> "preferences".
>
> The following relies on undocumented (I hope) behaviour:
What bit are you suggesting is undocumented?
>>>> preferences = [10, 30, 20]
>>>> hosts = [ "mx1.domain.com", "anotherhost.domain.com",
>... "mx2.domain.com"]
>>>> hosts.sort(key=lambda x, p=iter(preferences).next: p())
>>>> preferences.sort()
>>>> hosts
> ['mx1.domain.com', 'mx2.domain.com', 'anotherhost.domain.com']
>>>> preferences
> [10, 20, 30]
Now if you wanted to claim it was opaque and confusing, I'd agree with
you :-)
Here's a function that uses the Decorate-Sort-Undecorate technique to
sort one list by the contents of another:
from sys import maxint
_indices = xrange(maxint)
def sorterDSU(alist, blist):
"""Return a copy of alist sorted by the contents of blist."""
assert len(alist) == len(blist)
decorated = zip(blist, _indices, alist)
decorated.sort()
return [avalue for (bvalue, i, avalue) in decorated]
Here's another version:
def sorter(alist, blist):
assert len(alist) == len(blist)
table = sorted(range(len(alist)), key=blist.__getitem__)
return [alist[i] for i in table]
>>> alist = "John Eric Michael Graham Terry-J Terry-G".split()
>>> blist = [5, 0, 4, 1, 3, 2]
>>> sorter(alist, blist)
['Eric', 'Graham', 'Terry-G', 'Terry-J', 'Michael', 'John']
--
Steven
More information about the Python-list
mailing list