There's a bunch of questions that are phrased similarly, but I was unable to find one that actually mapped to my intended semantics.
There are two lists, A
and B
, and I want to rearrange B
so that it is in the same relative order as A
- the maximum element of B
is in the same position as the current position of the maximum element of A
, and the same for the minimum element, and so on.
Note that A
is not sorted, nor do I want it to be.
As an example, if the following were input:
a = [7, 14, 0, 9, 19, 9]
b = [45, 42, 0, 1, -1, 0]
I want the output to be [0, 42, -1, 0, 45, 1]
.
Please note that the intended output is not [0, 45, 1, 0, 42, -1]
, which is what it would be it you zipped the two and sorted by A
and took the resulting elements of B
(this is what all of the other questions I looked at wanted).
Here's my code:
def get_swaps(x):
out = []
if len(x) <= 1:
return out
y = x[:]
n = -1
while len(y) != 1:
pos = y.index(max(y))
y[pos] = y[-1]
y.pop()
out.append((pos, n))
n -= 1
return out
def apply_swaps_in_reverse(x, swaps):
out = x[:]
for swap in swaps[::-1]:
orig, new = swap
out[orig], out[new] = out[new], out[orig]
return out
def reorder(a, b):
return apply_swaps_in_reverse(sorted(b), get_swaps(a))
The approach is basically to construct a list of the swaps necessary to sort A
via selection sort, sort B
, and then apply those swaps in reverse. This works, but is pretty slow (and is fairly confusing, as well). Is there a better approach to this?
a = [7, 14, 0, 9, 19, 9]
b = [45, 42, 0, 1, -1, 0]
print zip(*sorted(zip(sorted(b), sorted(enumerate(a), key=lambda x:x[1])), key=lambda x: x[1][0]))[0]
#or, for 3.x:
print(list(zip(*sorted(zip(sorted(b), sorted(enumerate(a), key=lambda x:x[1])), key=lambda x: x[1][0])))[0])
result:
(0, 42, -1, 0, 45, 1)
You sort a
, using enumerate
to keep track of each item's original index. You zip the result with sorted(b)
, then re-sort the whole thing based on a
's original indices. Then you call zip
once more to extract just b
's values.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With