У меня есть массив:
b = [1,2,3,4,5,6,7,8,9,10,11]
Я хочу изменить индекс элементов в б на основе этого:
ind = [6, 4, 3, 9, 10, 8, 1, 5, 2, 7, 0]
Модифицированный правильныйб будет:
modified_b = [11,7,9,3,2,8,1,10,6,4,5]
Вот что я пробовал:
b = [1,2,3,4,5,6,7,8,9,10,11]
ind = [6, 4, 3, 9, 10, 8, 1, 5, 2, 7, 0]
b_modified = []
for j in range(0,len(b)):
b_modified.insert(ind[j],b[j])
print (b_modified)
Результаты неверны:
[11, 1, 7, 9, 2, 3, 4, 8, 10, 5, 6]
Есть идеи, как это сделать на Python?






Создайте новый пустой массив и назначьте индексы:
b = [1,2,3,4,5,6,7,8,9,10,11]
ind = [6, 4, 3, 9, 10, 8, 1, 5, 2, 7, 0]
b_modified = [0] * len(b)
for i in range(len(ind)):
b_modified[ind[i]] = b[i]
print(b_modified)
>>> [11,7,9,3,2,8,1,10,6,4,5]
Сделать это можно с помощью встроенной функции sort типа list:
sorted(b, key=lambda x: ind[x-1])
вернет новый список, отсортированный по желанию.
Если вы хотите выполнить сортировку на месте:
b.sort(key=lambda x: ind[x-1])
Вы можете создать новый список на основе заархивированного объекта индекса и значений:
>>> [t[1] for t in sorted(zip(ind,b))]
[11, 7, 9, 3, 2, 8, 1, 10, 6, 4, 5]
Или выполните назначение среза, чтобы изменить b на месте:
>>> b[:]=[t[1] for t in sorted(zip(ind,b))]
>>> b
[11, 7, 9, 3, 2, 8, 1, 10, 6, 4, 5]
Это будет иметь разумную производительность в списках O(n log n) малого и среднего размера. Если скорость вызывает беспокойство, вы можете заменить соответствующие элементы напрямую, используя enumerate, чтобы получить O(n):
mod_b=[None]*len(b)
for i,x in enumerate(ind):
mod_b[x]=b[i]
>>> mod_b
[11, 7, 9, 3, 2, 8, 1, 10, 6, 4, 5]
В общем случае сортировка занимает время O (п log п), тогда как времени O (п) должно быть достаточно. Для решения O (п) вы можете использовать цикл for с zip:
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
ind = [6, 4, 3, 9, 10, 8, 1, 5, 2, 7, 0]
res = [0] * len(b)
for val, idx in zip(b, ind):
res[idx] = val
# [11, 7, 9, 3, 2, 8, 1, 10, 6, 4, 5]
list.insert здесь не подходит, так как вы не можете получить доступ к индексам, которых еще нет в списке. Поскольку вы заранее знаете размер своего результата, вы можете просто создать список с этим размером.
Вы также можете использовать сторонний NumPy, который поддерживает векторизованное индексирование:
import numpy as np
b = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
ind = np.array([6, 4, 3, 9, 10, 8, 1, 5, 2, 7, 0])
res = np.empty(b.shape)
res[ind] = b
# array([11., 7., 9., 3., 2., 8., 1., 10., 6., 4., 5.])
Используя NumPy, как предлагает jpp, но для завершения списка используйте метод tolist ():
b = [1,2,3,4,5,6,7,8,9,10,11]
ind = [6, 4, 3, 9, 10, 8, 1, 5, 2, 7, 0]
c=np.array(b)[ind].tolist()
Спасибо! Мне больше понравилось ваше последнее решение!