将列表与另一个列表的顺序相同

时间:2016-09-28 18:27:13

标签: python list sorting

有很多类似的措辞,但是我无法找到一个实际映射到我预期语义的问题。

有两个列表,AB,我想重新排列B,使其与A处于相同的相对顺序 - 最大元素BA的最大元素的当前位置位于相同的位置,最小元素的位置相同,依此类推。

请注意,A未排序,我也不希望它排序。

例如,如果输入以下内容:

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

我希望输出为[0, 42, -1, 0, 45, 1]

请注意,预期的输出不是[0, 45, 1, 0, 42, -1],这就是您将两者压缩并按A排序并获取B的结果元素(这是我所看到的所有其他问题都需要。)

这是我的代码:

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))

该方法基本上是通过选择排序,排序A来构建排序B所需的交换列表,然后反向应用这些交换。这有效,但速度很慢(而且相当混乱)。有更好的方法吗?

2 个答案:

答案 0 :(得分:5)

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])

结果:

(0, 42, -1, 0, 45, 1)

您使用aenumerate进行排序,以跟踪每个项目的原始索引。您使用sorted(b)压缩结果,然后根据a的原始索引对整个内容进行重新排序。然后,再次致电zip,只提取b的值。

答案 1 :(得分:3)

您可以使用numpy轻松完成此操作,方法是对两个列表进行排序(以获取两个列表之间的映射)并反转其中一个排序排列:

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])

numpy.argsort给出了对数组进行排序的索引(置换)。这需要反转以在b内使用,这可以通过反向赋值

来完成
aiinv[ai] = np.arange(a.size)