Suppose I have:
list1 = [3, 2, 4, 1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']
Calling list1.sort() will sort it, resulting in [1, 1, 2, 3, 4]. However, can I get list2 to be rearranged in sync with that, to get a result like this?
list1 = [1, 1, 2, 3, 4]
list2 = ['one', 'one2', 'two', 'three', 'four']
Sometimes, people phrase the problem differently: given two lists, they would like to use one to determine the sort order for the other – i.e., sort list2 in the order described by the corresponding values in list1. The trick is that this is equivalent to sorting the "key" values (list1), and then rearranging list2 in the same way. In other words, exactly what is described here. Some answers for the other question, though, discard the "sorted keys" afterwards.
See also: How can I sort a list, according to where its elements appear in another list? – this is another common way that people want to sort one list "based on" another. Before attempting to close duplicate questions, take special care to check exactly what the OP wants. A key clue: do the lists need to be the same length?
One classic approach to this problem is to use the "decorate, sort, undecorate" idiom, which is especially simple using python’s built-in
zipfunction:These of course are no longer lists, but that’s easily remedied, if it matters:
It’s worth noting that the above may sacrifice speed for terseness; the in-place version, which takes up 3 lines, is a tad faster on my machine for small lists:
On the other hand, for larger lists, the one-line version could be faster:
As Quantum7 points out, JSF’s suggestion is a bit faster still, but it will probably only ever be a little bit faster, because Python uses the very same DSU idiom internally for all key-based sorts. It’s just happening a little closer to the bare metal. (This shows just how well optimized the
ziproutines are!)I think the
zip-based approach is more flexible and is a little more readable, so I prefer it.Note that when elements of
list1are equal, this approach will end up comparing elements oflist2. If elements oflist2don’t support comparison, or don’t produce a boolean when compared (for example, iflist2is a list of NumPy arrays), this will fail, and if elements oflist2are very expensive to compare, it might be better to avoid comparison anyway.In that case, you can sort indices as suggested in jfs’s answer, or you can give the sort a key function that avoids comparing elements of
list2:Also, the use of
zip(*...)as a transpose fails when the input is empty. If your inputs might be empty, you will have to handle that case separately.