Подтвердить что ты не робот

Как получить индексы отсортированного массива в Python

У меня есть числовой список:

myList = [1, 2, 3, 100, 5]

Теперь, если я отсортирую этот список для получения [1, 2, 3, 5, 100]. Я хочу индексы элементов из исходный список в отсортированном порядке, т.е. [0, 1, 2, 4, 3] --- ala Функция сортировки MATLAB, которая возвращает оба значений и индексов.

4b9b3361

Ответ 1

Если вы используете numpy, у вас есть доступная функция argsort():

>>> import numpy
>>> numpy.argsort(myList)
array([0, 1, 2, 4, 3])

http://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html

Это возвращает аргументы, которые будут сортировать массив или список.

Ответ 2

Что-то вроде следующего:

>>> myList = [1, 2, 3, 100, 5]
>>> [i[0] for i in sorted(enumerate(myList), key=lambda x:x[1])]
[0, 1, 2, 4, 3]

enumerate(myList) дает список, содержащий кортежи (index, value):

[(0, 1), (1, 2), (2, 3), (3, 100), (4, 5)]

Вы сортируете список, передавая его в sorted и определяя функцию для извлечения ключа сортировки (второй элемент каждого кортежа, для чего используется lambda). Наконец, исходный индекс каждого отсортированного элемента извлечение с использованием понимания списка [i[0] for i in ...].

Ответ 3

myList = [1, 2, 3, 100, 5]    
sorted(range(len(myList)),key=myList.__getitem__)

[0, 1, 2, 4, 3]

Ответ 4

Ответы с enumerate хороши, но мне лично не нравится, что лямбда используется для сортировки по значению. Следующие просто меняют индекс и значение и сортируют его. Поэтому сначала он сортируется по значению, затем по индексу.

sorted((e,i) for i,e in enumerate(myList))

Ответ 5

Обновлен ответ с помощью enumerate и itemgetter:

sorted(enumerate(a), key=lambda x: x[1])
# [(0, 1), (1, 2), (2, 3), (4, 5), (3, 100)]

Запишите списки вместе: первый элемент в кортеже будет индексом, второй - значением (затем отсортируйте его, используя второе значение кортежа x[1], x - кортеж)

Или используя itemgetter из модуля operator:

from operator import itemgetter
sorted(enumerate(a), key=itemgetter(1))

Ответ 6

Если вы не хотите использовать NumPy,

sorted(range(len(seq)), key=seq.__getitem__)

самый быстрый, как показано здесь.

Ответ 7

Я быстро проверил их производительность с помощью perfplot (мой проект) и обнаружил, что трудно порекомендовать что-либо еще, кроме numpy (обратите внимание на масштаб журнала):

enter image description here


Код для воспроизведения сюжета:

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,
)

Ответ 8

Другие ответы НЕПРАВИЛЬНЫ.

Запуск argsort один раз не является решением. Например, следующий код:

import numpy as np
x = [3,1,2]
np.argsort(x)

дает array([1, 2, 0], dtype=int64) который не является тем, что мы хотим.

Ответ должен состоять в том, чтобы запустить argsort дважды:

import numpy as np
x = [3,1,2]
np.argsort(np.argsort(x))

выдает array([2, 0, 1], dtype=int64) как и ожидалось.

Ответ 9

По сути, вам нужно сделать argsort, какая реализация вам нужна, зависит от того, хотите ли вы использовать внешние библиотеки (например, NumPy) или хотите остаться чистым Python без зависимостей.

Вопрос, который вам нужно задать себе: хотите ли вы

  • индексы, которые будут сортировать массив/список
  • индексы, которые элементы будут иметь в отсортированном массиве/списке

К сожалению, пример в вопросе не проясняет, что нужно, потому что оба приведут к одному и тому же результату:

>>> 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)

Выбор реализации argsort

Если у вас есть NumPy, вы можете просто использовать функцию numpy.argsort или метод numpy.ndarray.argsort.

Реализация без NumPy уже упоминалась в некоторых других ответах, поэтому я просто напомню самое быстрое решение в соответствии с ответом теста здесь

def argsort(l):
    return sorted(range(len(l)), key=l.__getitem__)

Получение индексов, которые будут сортировать массив/список

Чтобы получить индексы, которые будут сортировать массив/список, вы можете просто вызвать argsort в массиве или списке. Я использую здесь версии NumPy, но реализация Python должна давать те же результаты

>>> arr = np.array([3, 1, 2, 4])
>>> np.argsort(arr)
array([1, 2, 0, 3], dtype=int64)

Результат содержит индексы, необходимые для получения отсортированного массива.

Поскольку отсортированный массив будет [1, 2, 3, 4], массив argsorted содержит индексы этих элементов в оригинале.

  • Наименьшее значение - 1, и оно имеет индекс 1 в оригинале, поэтому первый элемент результата - 1.
  • 2 имеет индекс 2 в оригинале, поэтому вторым элементом результата является 2.
  • 3 имеет индекс 0 в оригинале, поэтому третий элемент результата - 0.
  • Наибольшее значение 4, оно по индексу 3 в оригинале, поэтому последний элемент результата - 3.

Получение индексов, которые элементы будут иметь в отсортированном массиве/списке

В этом случае вам нужно будет применить argsort дважды:

>>> 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.

Ответ 10

Импортировать numpy как np

ДЛЯ ИНДЕКСА

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 в отсортированном порядке.

НА СТОИМОСТЬ

np.sort(S)

[output]=array([ 0,  2,  3, 10, 11, 33, 44, 55, 66])

Ответ 11

Мы создадим еще один массив индексов от 0 до n-1 Затем заархивируйте его в исходный массив, а затем отсортируйте его на основе исходных значений

ar = [1,2,3,4,5]
new_ar = list(zip(ar,[i for i in range(len(ar))]))
new_ar.sort()

"