排序列表的反向索引

时间:2013-08-20 21:55:46

标签: python sorting

我想返回排序列表的' 反向 '索引。我的意思是:我有一个未排序的列表U,我通过S=sorted(U)对其进行排序。现在,我可以获得U(idx)=S的排序索引 - 但我想要S(Ridx) = U

这里有一个小例子:

U=[5,2,3,1,4]

S=sorted(U)

idx = [U.index(S[i]) for i in range(len(U))]
>>> idx
[3, 1, 2, 4, 0]

Ridx = [S.index(U[i]) for i in range(len(U))]
>>> Ridx
[4, 1, 2, 0, 3]

>>>[U[idx[i]] for i in range(len(U))] == S
True

>>>[S[Ridx[i]] for i in range(len(U))] == U
True

我需要的是获得Ridx的有效方法。

谢谢!


编辑:

好的,好的!我对这两个问题的解决方案(@Jon Clements和@Whatang)进行了一次速度测试。

剧本:

import datetime as DT
import random

U=[int(1000*random.random()) for i in xrange(pow(10,8))]

S=sorted(U)

idx = sorted(xrange(len(U)), key=U.__getitem__)

T0 = DT.datetime.now()
ridx = sorted(xrange(len(U)), key=idx.__getitem__)
print [S[ridx[i]] for i in range(len(U))]==U
elapsed = DT.datetime.now()-T0
print str(elapsed)

print '==============='
T0 = DT.datetime.now()
ridx = [ y for (x,y) in sorted(zip(idx, range(len(idx)))) ]
print [S[ridx[i]] for i in range(len(U))]==U
elapsed = DT.datetime.now()-T0
print str(elapsed)

结果:

True
0:02:45.278000
===============
True
0:06:48.889000

谢谢大家的快速而有意义的帮助!

5 个答案:

答案 0 :(得分:5)

我能想到的最有效率(缺少可能期待numpy)摆脱.index并且可用于idxridx

U=[5,2,3,1,4]
idx = sorted(xrange(len(U)), key=U.__getitem__)
ridx = sorted(xrange(len(U)), key=idx.__getitem__)
# [3, 1, 2, 4, 0] [4, 1, 2, 0, 3]

答案 1 :(得分:2)

不是您要求的数据结构,但我认为这可以获得您想要的信息:

>>> sorted(x[::-1] for x in enumerate(['z', 'a', 'c', 'x', 'm']))
[('a', 1), ('c', 2), ('m', 4), ('x', 3), ('z', 0)]

答案 2 :(得分:2)

你可以用numpy做

>>> import numpy as np
>>> U = [5, 2, 3, 1, 4]

>>> np.array(U).argsort().argsort()
array([4, 1, 2, 0, 3])

答案 3 :(得分:1)

假设您已经拥有列表idx,则可以

ridx = [ y for (x,y) in sorted(zip(idx, range(len(idx)))) ]

然后适用于从0到i

的所有len(U)
S[ridx[i]] == U[i]

如果使用字典,可以避免排序:

ridx_dict = dict(zip(idx, range(len(idx))))

然后可以转换为列表:

ridx = [ ridx_dict[k] for k in range(len(idx)) ]

考虑排列是这个问题的关键。写下排列的一种方法是在一行上按顺序写入所有索引,然后在下面的行上用该索引写入元素的新索引。例如,为您的例子

0 1 2 3 4
3 1 2 4 0

第二行是您的idx列表。你读下了列,所以从索引0开始的元素移动到索引3,从索引1开始的元素停留在索引1,依此类推。

inverse permutation是您要找的ridx。要找到这个,请将排列的下面一行排列在一起,然后记下新的顶行。所以这个例子就变成了:

4 1 2 0 3
0 1 2 3 4

答案 4 :(得分:0)

如果我正确地理解了这个问题(我没有这样做),我认为U.index(S [i])就是你要找的东西

编辑:所以我猜你可以保存原始索引的字典并保持检索语法非常简单

OIDX = {U[i]: i for i in range(0, len(U))}
S = sorted(U)
OIDX[S[i]]