由于[4, 5, 6] 和[2, 3, 1] 有两个不同的用途,我将创建一个带有两个 参数的函数:要重新排序的列表,以及排序将决定顺序的列表。我只会返回重新排序的列表。
This answer 具有三种不同解决方案的时序,用于为排序创建排列列表。使用最快的选项给出了这个解决方案:
def pyargsort(seq):
return sorted(range(len(seq)), key=seq.__getitem__)
def using_pyargsort(a, b):
"Reorder the list a the same way as list b would be reordered by a normal sort"
return [a[i] for i in pyargsort(b)]
print using_pyargsort([4, 5, 6], [2, 3, 1]) # [6, 4, 5]
pyargsort 方法的灵感来自 numpy argsort 方法,它做同样的事情要快得多。 Numpy 还具有高级索引操作,可以将数组用作索引,从而可以非常快速地重新排序数组。
因此,如果您对速度的需求很大,人们会认为这种 numpy 解决方案会更快:
import numpy as np
def using_numpy(a, b):
"Reorder the list a the same way as list b would be reordered by a normal sort"
return np.array(a)[np.argsort(b)].tolist()
print using_numpy([4, 5, 6], [2, 3, 1]) # [6, 4, 5]
但是,对于短列表(长度 a 和b 列表转换为array,然后在返回之前将结果转换回list。如果我们假设您在整个应用程序中使用 numpy 数组,这样我们就不需要来回转换,我们会得到以下解决方案:
def all_numpy(a, b):
"Reorder array a the same way as array b would be reordered by a normal sort"
return a[np.argsort(b)]
print all_numpy(np.array([4, 5, 6]), np.array([2, 3, 1])) # array([6, 4, 5])
all_numpy 函数的执行速度比 using_pyargsort 函数快 10 倍。
以下对数图将这三个解决方案与其他答案中的两个替代解决方案进行了比较。参数是两个随机打乱的等长范围,并且函数都接收相同排序的列表。我只计算函数执行的时间。出于说明目的,我为每个 numpy 解决方案添加了一条额外的图表线,其中加载 numpy 的 60 毫秒开销被添加到时间中。
正如我们所见,全 numpy 解决方案比其他解决方案高出一个数量级。相比之下,从 python list 转换并返回会大大降低 using_numpy 解决方案的速度,但对于大型列表,它仍然优于纯 python。
对于大约 1'000'000 的列表长度,using_pyargsort 需要 2.0 秒,using_nympy + 开销仅为 1.3 秒,而all_numpy + 开销为 0.3 秒。