By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,627 Members | 1,211 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,627 IT Pros & Developers. It's quick & easy.

How do I sort these?

P: n/a
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?

Oct 28 '05 #1
Share this Question
Share on Google+
15 Replies


P: n/a
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?


I guess you mean that you have two lists of same size where each index
position pointing to corrsponding items - like two excel columns? Then
this helps:

sl = zip(list_a, list_b)
sl.sort()
list_a, list_b = unzip(*sl)

Regards,

Diez
Oct 28 '05 #2

P: n/a
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?

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006 www.python.org/pycon/

Oct 28 '05 #3

P: n/a
yes... Thats the idea...

Oct 28 '05 #4

P: n/a
In C++ you can specify a comparision method, how can I do this with
python...
Say for instance the first list was a dictionary and I wanted to sort
on one of the keys in the dictionary?

Oct 28 '05 #5

P: n/a
unzip doesn't seem to work for me...

Oct 28 '05 #6

P: n/a
"KraftDiner" <bo*******@yahoo.com> writes:
In C++ you can specify a comparision method, how can I do this with
python...


Yes, see the docs. Just pass a comparison func to the sort method.
Oct 28 '05 #7

P: n/a
> unzip doesn't seem to work for me...

It's not a part of the standard Python distribution, but this is a
naive implementation (it doesn't react well to the list's contents
having different lengths).

def unzip(seq):
result = [[] for i in range(len(seq[0]))]
for item in seq:
for index in range(len(item)):
result[index].append(item[index])
return result
unzip(zip(range(5), 'abcde'))

[[0, 1, 2, 3, 4], ['a', 'b', 'c', 'd', 'e']]

Oct 28 '05 #8

P: n/a
Sam Pointon a écrit :
unzip doesn't seem to work for me...

It's not a part of the standard Python distribution, but this is a
naive implementation (it doesn't react well to the list's contents
having different lengths).

def unzip(seq):
result = [[] for i in range(len(seq[0]))]
for item in seq:
for index in range(len(item)):
result[index].append(item[index])
return result

unzip(zip(range(5), 'abcde'))
[[0, 1, 2, 3, 4], ['a', 'b', 'c', 'd', 'e']]


unzip() could be also be written like this:

def unzip(seq):
return zip(*seq)

Faster and nicer, isn't it?

Except that it returns a list of tuples:
unzip(zip(range(5), 'abcde'))

[(0, 1, 2, 3, 4), ('a', 'b', 'c', 'd', 'e')]

--
Amaury
Oct 28 '05 #9

P: n/a
On Fri, 28 Oct 2005 13:42:49 -0700, KraftDiner wrote:
unzip doesn't seem to work for me...


Nor for me:
unzip

Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'unzip' is not defined
I don't think it exists.

But it is easy enough to create:

def unzip(L):
"""Reverse a zip.

Expects L to be a list of the form:
[(1, 'a'), (2, 'b'), (3, 'c')]
and returns:
[(1, 2, 3), ('a', 'b', 'c')]

Note that unzip(zip(seq1, seq2)) is not quite a null-op,
because some type information is lost, e.g. lists and
strings are converted into tuples.
"""
return zip(*L)

As you can see, the documentation for unzip is longer than the code itself :-)

--
Steven.

Oct 29 '05 #10

P: n/a
Paul Rubin <http://ph****@NOSPAM.invalid> wrote:
"KraftDiner" <bo*******@yahoo.com> writes:
In C++ you can specify a comparision method, how can I do this with
python...


Yes, see the docs. Just pass a comparison func to the sort method.


Or, better, pass a key-extraction function, that's much handier and
faster (it automates the "decorate-sort-undecorate", DSU, idiom).
Alex
Oct 29 '05 #11

P: n/a
KraftDiner wrote:
unzip doesn't seem to work for me...


Mrmpf, my bad. The operation is called unzip, but implpemented by using
zip - so
unzip(l) == zip(*l)
So the exchange unzip with zip in my example.

Diez
Oct 29 '05 #12

P: n/a
On Fri, 28 Oct 2005 20:00:42 +0100, Steve Holden <st***@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? ;-)

Regards,
Bengt Richter
Oct 30 '05 #13

P: n/a
Bengt Richter wrote:
On Fri, 28 Oct 2005 20:00:42 +0100, Steve Holden <st***@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

Oct 30 '05 #14

P: n/a
# This can be a solution:

from operator import itemgetter
seq1a = ([2] * 4) + ([1] * 4)
seq2a = [complex(3-el,7-el) for el in range(1, 9)]
assert len(seq1a) == len(seq2a)
print seq1a, seq2a, "\n"

mix = zip(seq1a, seq2a)
# mix.sort() # Not possible
mix.sort(key=itemgetter(0))

# If you need tuples output:
seq1b, seq2b = zip(*mix)
print seq1b, seq2b, "\n"

# Alternative, lists output:
seq1b = [el[0] for el in mix]
seq2b = [el[1] for el in mix]
print seq1b, seq2b, "\n"

Bye,
bearophile

Oct 30 '05 #15

P: n/a
On Sun, 30 Oct 2005 10:13:42 +0100, Peter Otten <__*******@web.de> wrote:
Bengt Richter wrote:

[...]
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']

D'oh yeah, forgot about key ;-/ (and this kind of problem probably at least
partly motivated its introduction, so it should have jumped to mind).
Thanks, your version is much cleaner ;-)

Regards,
Bengt Richter
Oct 30 '05 #16

This discussion thread is closed

Replies have been disabled for this discussion.