440,627 Members | 1,211 Online
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
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" 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 resultunzip(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 "", 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 wrote: "KraftDiner" 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 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 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 providethe 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.