How to get indices of a sorted array in Python
我有一个数字列表:
1 | myList = [1, 2, 3, 100, 5] |
现在,如果我对该列表进行排序以获得
我想要的是来自
按排序顺序的原始列表,即
--- ala同时返回两个
值和索引。
如果使用的是numpy,则可以使用argsort()函数:
1 2 3 | >>> import numpy >>> numpy.argsort(myList) array([0, 1, 2, 4, 3]) |
http://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html
这将返回对数组或列表进行排序的参数。
如下所示:
1 2 3 | >>> myList = [1, 2, 3, 100, 5] >>> [i[0] for i in sorted(enumerate(myList), key=lambda x:x[1])] [0, 1, 2, 4, 3] |
1 | [(0, 1), (1, 2), (2, 3), (3, 100), (4, 5)] |
您可以通过将列表传递给
1 2 3 4 | myList = [1, 2, 3, 100, 5] sorted(range(len(myList)),key=myList.__getitem__) [0, 1, 2, 4, 3] |
1 | sorted((e,i) for i,e in enumerate(myList)) |
用
1 2 | sorted(enumerate(a), key=lambda x: x[1]) # [(0, 1), (1, 2), (2, 3), (4, 5), (3, 100)] |
将列表压缩在一起:元组中的第一个元素将是索引,第二个是值(然后使用元组
或使用
1 2 | from operator import itemgetter sorted(enumerate(a), key=itemgetter(1)) |
如果您不想使用numpy,
1 | sorted(range(len(seq)), key=seq.__getitem__) |
如此处所示,最快。
我用perfplot(我的一个项目)对这些进行了快速性能检查,发现很难推荐除numpy以外的其他任何东西(请注意对数刻度):
复制剧情的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | import perfplot import numpy def sorted_enumerate(seq): return [i for (v, i) in sorted((v, i) for (i, v) in enumerate(seq))] def sorted_enumerate_key(seq): return [x for x, y in sorted(enumerate(seq), key=lambda x: x[1])] def sorted_range(seq): return sorted(range(len(seq)), key=seq.__getitem__) def numpy_argsort(x): return numpy.argsort(x) perfplot.save( "argsort.png", setup=lambda n: numpy.random.rand(n), kernels=[sorted_enumerate, sorted_enumerate_key, sorted_range, numpy_argsort], n_range=[2 ** k for k in range(15)], xlabel="len(x)", logx=True, logy=True, ) |
其他答案是错误的。
一次运行
例如,以下代码:
1 2 3 | import numpy as np x = [3,1,2] np.argsort(x) |
产生
答案应该是两次运行
1 2 3 | import numpy as np x = [3,1,2] np.argsort(np.argsort(x)) |
按预期给出
从本质上讲,您需要执行
您需要问自己的问题是:您是否想要
- 对数组/列表进行排序的索引
- 元素在排序数组/列表中将具有的索引
不幸的是,问题中的示例并未明确说明所需的内容,因为两者都会给出相同的结果:
1 2 3 4 5 6 7 | >>> arr = np.array([1, 2, 3, 100, 5]) >>> np.argsort(np.argsort(arr)) array([0, 1, 2, 4, 3], dtype=int64) >>> np.argsort(arr) array([0, 1, 2, 4, 3], dtype=int64) |
选择
如果可以使用NumPy,则可以简单地使用函数
已经在其他一些答案中提到了没有NumPy的实现,因此我将根据此处的基准答案来概述最快的解决方案
1 2 | def argsort(l): return sorted(range(len(l)), key=l.__getitem__) |
获取将对数组/列表进行排序的索引
要获取对数组/列表进行排序的索引,您只需在数组或列表上调用
1 2 3 | >>> arr = np.array([3, 1, 2, 4]) >>> np.argsort(arr) array([1, 2, 0, 3], dtype=int64) |
结果包含获取排序数组所需的索引。
由于排序后的数组为
-
最小值为
1 ,并且在原始索引中的索引为1 ,因此结果的第一个元素为1 。 -
2 在原始索引中位于索引2 ,因此结果的第二个元素是2 。 -
3 在原始索引中的索引为0 ,因此结果的第三个元素为0 。 -
最大值
4 ,它在原始索引中的索引为3 ,因此结果的最后一个元素为3 。
获取元素在已排序数组/列表中的索引
在这种情况下,您需要两次应用
1 2 3 | >>> arr = np.array([3, 1, 2, 4]) >>> np.argsort(np.argsort(arr)) array([2, 0, 1, 3], dtype=int64) |
在这种情况下 :
-
原始元素的第一个元素是
3 ,这是第三大值,因此它在排序的数组/列表中将具有索引2 ,因此第一个元素是2 。 -
原始元素的第二个元素是
1 ,这是最小值,因此在已排序的数组/列表中将具有索引0 ,因此第二个元素是0 。 -
原始元素的第三个元素是
2 ,这是第二个最小的值,因此在排序后的数组/列表中将具有索引1 ,因此第三个元素是1 。 -
原始元素的第四个元素是
4 ,这是最大值,因此在已排序的数组/列表中将具有索引3 ,因此最后一个元素是3 。
我们将创建从0到n-1的另一个索引数组
然后将其压缩到原始数组,然后根据原始值对其进行排序
1 2 3 | ar = [1,2,3,4,5] new_ar = list(zip(ar,[i for i in range(len(ar))])) new_ar.sort() |
`
将numpy导入为np
索引
1 2 3 4 5 | S=[11,2,44,55,66,0,10,3,33] r=np.argsort(S) [output]=array([5, 1, 7, 6, 0, 8, 2, 3, 4]) |
argsort按排序顺序返回S的索引
物有所值
1 2 3 | np.sort(S) [output]=array([ 0, 2, 3, 10, 11, 33, 44, 55, 66]) |