Putting a list in the same order as another list
<p>There's a bunch of questions that are phrased similarly, but I was unable to find one that actually mapped to my intended semantics.</p>

<p>There are two lists, <code>A</code> and <code>B</code>, and I want to rearrange <code>B</code> so that it is in the same relative order as <code>A</code> - the maximum element of <code>B</code> is in the same position as the current position of the maximum element of <code>A</code>, and the same for the minimum element, and so on.</p>

<p>Note that <code>A</code> is not sorted, nor do I want it to be.</p>

<p>As an example, if the following were input:</p>

<pre><code>a = [7, 14, 0, 9, 19, 9]
b = [45, 42, 0, 1, -1, 0]
</code></pre>

<p>I want the output to be <code>[0, 42, -1, 0, 45, 1]</code>.</p>

<p>Please note that the intended output is not <code>[0, 45, 1, 0, 42, -1]</code>, which is what it would be it you zipped the two and sorted by <code>A</code> and took the resulting elements of <code>B</code> (this is what all of the other questions I looked at wanted).</p>

<p>Here's my code:</p>

<pre><code>def get_swaps(x):
    out = []

    if len(x) &lt;= 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))
</code></pre>

<p>The approach is basically to construct a list of the swaps necessary to sort <code>A</code> via selection sort, sort <code>B</code>, 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?</p>

<p>You can easily do this with <code>numpy</code> by sorting both lists (to get a mapping between the two lists) and by inverting one of the sorting permutations:</p>

<pre><code>import numpy as np

a = [7, 14, 0, 9, 19, 9]
b = [45, 42, 0, 1, -1, 0]

a = np.array(a)
b = np.array(b)

ai = np.argsort(a)
bi = np.argsort(b)
aiinv = np.empty(ai.shape,dtype=int)
aiinv[ai] = np.arange(a.size)  # inverse of ai permutation

b_new = b[bi[aiinv]]
# array([ 0, 42, -1,  0, 45,  1])
</code></pre>

<p><a href="http://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html" rel="nofollow"><code>numpy.argsort</code></a> gives the indices (permutation) that will sort your array. This needs to be inverted to be used inside <code>b</code>, which can be done by the inverted assignment</p>

<pre><code>aiinv[ai] = np.arange(a.size)
</code></pre>

python list sorting