How do I sort these?

Peter Otten __peter__ at web.de
Sun Oct 30 04:13:42 EST 2005


Bengt Richter wrote:

> On Fri, 28 Oct 2005 20:00:42 +0100, Steve Holden <steve at holdenweb.com>
> wrote:
> 
>>KraftDiner wrote:
>>> I have two lists.
>>> I want to sort by a value in the first list and have the second list
>>> sorted as well... Any suggestions on how I should/could do this?
>>> 
>> >>> first = [1, 3, 5, 7, 9, 2, 4, 6, 8]
>> >>> second = ['one', 'three', 'five', 'seven', 'nine', 'two', 'four',
>>'six', 'eight']
>> >>> both = zip(first, second)
>> >>> both.sort()
>> >>> [b[0] for b in both]
>>[1, 2, 3, 4, 5, 6, 7, 8, 9]
>> >>> [b[1] for b in both]
>>['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
>> >>>
>>
>>You mean like this?
> ISTM there could be a subtle requirement in the way the OP stated what he
> wanted to do. I.e., it sounds like he would like to sort the first list
> and have a second list undergo the same shuffling as was required to sort
> the first. That's different from having the data of the second participate
> in the sort as order-determining data, if equals in the first list are not
> to be re-ordered:
> 
>  >>> first = [2]*5 + [1]*5
>  >>> first
>  [2, 2, 2, 2, 2, 1, 1, 1, 1, 1]
>  >>> sorted(first)
>  [1, 1, 1, 1, 1, 2, 2, 2, 2, 2]
>  >>> second = [chr(ord('A')+i) for i in xrange(9,-1,-1)]
>  >>> second
>  ['J', 'I', 'H', 'G', 'F', 'E', 'D', 'C', 'B', 'A']
>  >>> sorted(second)
>  ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
> 
> Now the zipped sort unzipped:
>  >>> zip(*sorted(zip(first,second)))
>  [(1, 1, 1, 1, 1, 2, 2, 2, 2, 2), ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
>  ['I', 'J')]
> 
> Now suppose we sort the first and use the elements' indices to preserve
> order where equal
>  >>> sorted((f,i) for i,f in enumerate(first))
>  [(1, 5), (1, 6), (1, 7), (1, 8), (1, 9), (2, 0), (2, 1), (2, 2), (2, 3),
>  [(2, 4)]
> 
> Separate out the first list elements:
>  >>> [t[0] for t in sorted((f,i) for i,f in enumerate(first))]
>  [1, 1, 1, 1, 1, 2, 2, 2, 2, 2]
> 
> Now select from the second list, by first-element position correspondence:
>  >>> [second[t[1]] for t in sorted((f,i) for i,f in enumerate(first))]
>  ['E', 'D', 'C', 'B', 'A', 'J', 'I', 'H', 'G', 'F']
> 
> Which did the OP really want? ;-)

I don't know, but there certainly is no subtle requirement to not provide
the key argument:

>>> import operator
>>> first = [2]*5 + [1]*5
>>> second = list(reversed("ABCDEFGHIJ"))
>>> [s for f, s in sorted(zip(first, second))]
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
>>> [s for f, s in sorted(zip(first, second), key=operator.itemgetter(0))]
['E', 'D', 'C', 'B', 'A', 'J', 'I', 'H', 'G', 'F']

Peter




More information about the Python-list mailing list