用 Python 列表中的值交换索引?

Swapping indices with values in a Python list?

(不,这不是家庭作业也不是竞赛,尽管它看起来像一个。)

我在 Python 中有一个列表 A,其中包含数字 range(0, len(A))。数字不分先后,但都在列表中。

我正在寻找一种简单的方法来构建列表 B,其中交换了索引和值,即对于每个整数 n,包含 [的位置的列表=16=] 在 A.

示例:

A = [0, 4, 1, 3, 2]
B = [0, 2, 4, 3, 1]

我可以将生成 B 的代码单独放在生成 A 的代码中。特别是,这是我生成 A:

的方式
A = [value(i) for i in range(length)]

执行此操作的最佳方法是什么?

在值上使用 enumerate() function to decorate each value with their index, sorting with sorted(),然后再次取消修饰以按值顺序提取索引:

[i for i, v in sorted(enumerate(A), key=lambda iv: iv[1])]

这有一个 O(NlogN) 的时间复杂度,因为我们使用了排序。

演示:

>>> A = [0, 4, 1, 3, 2]
>>> [i for i, v in sorted(enumerate(A), key=lambda iv: iv[1])]
[0, 2, 4, 3, 1]

我们还可以使用预建列表为 O(N) 解决方案分配索引:

B = [0] * len(A)
for i, v in enumerate(A):
    B[v] = i

演示:

>>> B = [0] * len(A)
>>> for i, v in enumerate(A):
...     B[v] = i
... 
>>> B
[0, 2, 4, 3, 1]

如果时间复杂度是个大问题,这可能是更好的选择;对于 N = 100,排序方法将需要大约 461 个步骤,而预建列表方法需要 100 个步骤。

如何分配给预分配的B:

>>> A = [0, 4, 1, 3, 2]
>>> B = [0] * len(A)
>>> for k, v in enumerate(A): B[v] = k
>>> B
[0, 2, 4, 3, 1]

那将是 O(n)。

A = [0, 4, 1, 3, 2]

B = [None]*len(A)

for i, x in enumerate(A):
    B[x] = i

print B

结果:[0, 2, 4, 3, 1]

这太天真了;

[ [ x[0] for x in enumerate(A) if x[1] == i][0] for i in range(len(A)) ]

这很完美,

[A.index(A.index(i)) for i in A]  

更好

[A.index(i[0]) for i in enumerate(A)]

这个胜过另一个;

[A.index(i) for i in range(len(A))]

证明;

import random as r
for l in [ r.sample(range(5),5) for n in range(5) ]:
    A = l
    B = [A.index(A.index(i)) for i in A]
    print "A is : ", A
    print "B is : ", B
    print "Are B's elements indices of A? : ", A == [B.index(B.index(i)) for i in B]
    print