关于python:如何根据第二个索引列表重新排列一个列表

How to rearrange one list based on a second list of indices

本问题已经有最佳答案,请猛点这里访问。

我有一个10个项目的列表,还有一个10个随机不重复的数字列表,如下所示:

1
2
l = [a,b,c,d,e,f,g,h,i,j]
m = [1,4,5,9,2,6,3,7,8,10]

我想重新排列l,以便l中的每一项从m中取其相应的索引。

例如,b应该成为第四个,e应该成为第二个。

我对算法很在行,逻辑也让我抓狂,所以我不知道该如何处理这个问题。

我该怎么做?


如果您只是想让元素根据其他列表位置移动,那么可以循环遍历EDOCX1的所有元素(0),并使用列表理解来获取EDOCX1的元素(1)

1
l2 = [l[i - 1] for i in m]

但是,如果您希望基于其他列表进行排序,则需要将它们压缩在一起,对索引进行排序,然后提取元素

1
[y for x,y in sorted(zip(m,l))]


注:我假设m总是连续的(即没有"间隙"),从1开始。

如果是这样,你可以很容易地得到你想要的,使用列表理解,zip()sorted()

让我们一步一步来:

1
2
>>> l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
>>> m = [1, 4, 5, 9, 2, 6, 3, 7, 8, 10]

zip()m的每个元素与l的元素配对:

1
2
>>> zip(m, l)
[(1, 'a'), (4, 'b'), (5, 'c'), (9, 'd'), (2, 'e'), (6, 'f'), (3, 'g'), (7, 'h'), (8, 'i'), (10, 'j')]

sorted()返回对列表的排序副本:

1
2
>>> sorted(zip(m, l))
[(1, 'a'), (2, 'e'), (3, 'g'), (4, 'b'), (5, 'c'), (6, 'f'), (7, 'h'), (8, 'i'), (9, 'd'), (10, 'j')]

最后,列表理解只需要从每对列表中提取第二项:

1
2
>>> [x for i, x in sorted(zip(m, l))]
['a', 'e', 'g', 'b', 'c', 'f', 'h', 'i', 'd', 'j']


这可以在线性O(n)时间内通过听写完成:

1
2
3
4
5
6
7
8
l = ['a','b','c','d','e','f','g','h','i','j']
m = [ 1,  4,  5,  9,  2,  6,  3,  7,  8,  10]

values_by_index = dict(zip(m, l))
result = [values_by_index[index+1] for index in range(len(m))]

print(result)
# output: ['a', 'e', 'g', 'b', 'c', 'f', 'h', 'i', 'd', 'j']

第一行创建将索引映射到值的dict,如下所示:

1
2
>>> values_by_index
{1: 'a', 4: 'b', 5: 'c', 9: 'd', 2: 'e', 6: 'f', 3: 'g', 7: 'h', 8: 'i', 10: 'j'}

在第二行中,我们简单地循环索引1到10,并从dict中获取相应的值,这是平均情况下的O(1)操作。

如果有基于0的索引,只需从index+1中删除+1