l = [0, 1, 3, 2]
l2 = ['foo', 3, 'bar', 10]
If I say sorted(l)
, I will get [0, 1, 2, 3]
. It will swap the last two elements.
How can I apply the same row swaps to l2
? I.e., I want l2
to be ['foo', 3, 10, 'bar']
.
l = [0, 1, 3, 2]
l2 = ['foo', 3, 'bar', 10]
If I say sorted(l)
, I will get [0, 1, 2, 3]
. It will swap the last two elements.
How can I apply the same row swaps to l2
? I.e., I want l2
to be ['foo', 3, 10, 'bar']
.
You can use zip
, unpack tuple and a list comprehension to achieve the results:
[y for x, y in sorted(zip(l, l2))]
TL;DR
>>> l, l2 = zip(*sorted(zip(l, l2)))
>>> list(l)
[0, 1, 2, 3]
>>> list(l2)
['foo', 3, 10, 'bar']
Explanation
zip
both the lists together
>>> list(zip(l, l2))
[(0, 'foo'), (1, 3), (2, 10), (3, 'bar')]
then sort them, (since we get tuples from zip
, the first elements of tuples will be compared first and only if they are same, the second element will be compared. So the sorting effectively happens with the values of l
)
>>> sorted(zip(l, l2))
[(0, 'foo'), (1, 3), (2, 10), (3, 'bar')]
and then unzip them,
>>> list(zip(*sorted(zip(l, l2))))
[(0, 1, 2, 3), ('foo', 3, 10, 'bar')]
you can actually unzip over l
and l2
, like this
>>> l, l2 = zip(*sorted(zip(l, l2)))
>>> l, l2
((0, 1, 2, 3), ('foo', 3, 10, 'bar'))
>>> list(l)
[0, 1, 2, 3]
>>> list(l2)
['foo', 3, 10, 'bar']
Alternate approach
You can actually sort the values along with the current index and then you can reconstruct the values like this
>>> l = [0, 1, 3, 2]
>>> l2 = ['foo', 3, 'bar', 10]
>>> l_s = sorted((value, idx) for idx, value in enumerate(l))
>>> l_s
[(0, 0), (1, 1), (2, 3), (3, 2)]
>>> l = [value for value, idx in l_s]
>>> l
[0, 1, 2, 3]
>>> l2 = [l2[idx] for value, idx in l_s]
>>> l2
['foo', 3, 10, 'bar']