У меня есть числовой список:
myList = [1, 2, 3, 100, 5]
Теперь, если я сортирую этот список, чтобы получить [1, 2, 3, 5, 100]
. То, что я хочу, это индексы элементов из исходного списка в отсортированном порядке, т.е. [0, 1, 2, 4, 3]
--- функция сортировки MATLAB, которая возвращает и значения, и индексы.
Ответы:
Если вы используете numpy, у вас есть доступная функция argsort ():
http://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html
Это возвращает аргументы, которые будут сортировать массив или список.
источник
Примерно так:
enumerate(myList)
выдает список, содержащий кортежи (индекс, значение):Вы сортируете список, передавая его
sorted
и определяя функцию для извлечения ключа сортировки (второй элемент каждого кортежа; для этого и нуженlambda
. Наконец, исходный индекс каждого отсортированного элемента извлекается с использованием[i[0] for i in ...]
понимания списка.источник
itemgetter(1)
вместо лямбда-функцииitemgetter
функции вoperator
модуле, FYI. Так что,from operator import itemgetter
чтобы использовать это.sorted_items, sorted_inds = zip(*sorted([(i,e) for i,e in enumerate(my_list)], key=itemgetter(1)))
x = [3,1,2]; numpy.argsort(x)
дает [1,2,0].источник
Ответы
enumerate
хороши, но лично мне не нравится лямбда, используемая для сортировки по значению. Следующее просто инвертирует индекс и значение и сортирует их. Так что сначала он будет отсортирован по значению, а затем по индексу.источник
Обновленный ответ с
enumerate
иitemgetter
:Сжать списки вместе: первый элемент в кортеже будет индексом, второй - значением (затем отсортируйте его, используя второе значение кортежа
x[1]
, x - кортеж)Или используя
itemgetter
изoperator
модуля`:источник
Я быстро проверил их производительность с помощью perfplot ( мой проект) и обнаружил, что трудно рекомендовать что-либо еще, кроме numpy (обратите внимание на масштаб журнала):
Код для воспроизведения сюжета:
источник
Если вы не хотите использовать NumPy,
самый быстрый, как показано здесь .
источник
По сути, вам нужно сделать
argsort
, какая реализация вам нужна, зависит от того, хотите ли вы использовать внешние библиотеки (например, NumPy) или если вы хотите остаться чистым Python без зависимостей.Вопрос, который вы должны задать себе: вы хотите
К сожалению, пример в вопросе не проясняет, что нужно, потому что оба будут давать один и тот же результат:
Выбор
argsort
реализацииЕсли у вас есть NumPy, вы можете просто использовать функцию
numpy.argsort
или методnumpy.ndarray.argsort
.Реализация без NumPy уже упоминалась в некоторых других ответах, поэтому я просто напомню самое быстрое решение в соответствии с ответом на тестирование здесь
Получение индексов, которые будут сортировать массив / список
Чтобы получить индексы, которые будут сортировать массив / список, вы можете просто вызвать
argsort
массив или список. Я использую версии NumPy здесь, но реализация Python должна давать те же результатыРезультат содержит индексы, необходимые для получения отсортированного массива.
Поскольку отсортированный массив будет массивом
[1, 2, 3, 4]
argsorted, он содержит индексы этих элементов в оригинале.1
индексу1
в оригинале, поэтому первым элементом результата является1
.2
имеет2
оригинальное значение, поэтому второй элемент результата равен2
.3
Имеет индекс0
в оригинале , так что третий элемент результата0
.4
и оно по индексу3
в оригинале, поэтому последний элемент результата3
.Получение индексов, которые элементы будут иметь в отсортированном массиве / списке
В этом случае вам необходимо подать заявку
argsort
дважды :В таком случае :
3
, который является третьим по величине значением, поэтому он будет иметь индекс2
в отсортированном массиве / списке, поэтому первый элемент2
.1
это наименьшее значение, поэтому он будет иметь индекс0
в отсортированном массиве / списке, так что второй элемент -0
.2
это второе по наименьшему значению, поэтому он будет иметь индекс1
в отсортированном массиве / списке, так что третий элемент1
.4
это наибольшее значение, поэтому он будет иметь индекс3
в отсортированном массиве / списке, так что последний элемент3
.источник
Другие ответы НЕПРАВИЛЬНЫ.
Запуск
argsort
один раз не является решением. Например, следующий код:дает
array([1, 2, 0], dtype=int64)
не то, что мы хотим.Ответ должен быть запущен
argsort
дважды:дает,
array([2, 0, 1], dtype=int64)
как и ожидалось.источник
x[2]
(3) наименьший элемент иx[1]
(1) наибольший элемент (поскольку целые числа сортировки упорядочивают их от наименьшего значения к наибольшему значению). Кроме того, в примере с OP, одинnp.argsort([1, 2, 3, 100, 5])
выходarray([0, 1, 2, 4, 3])
, который, по-видимому, является индексами, которые хочет OP.arr = [1,2,3,100, 5, 9] res = np.argsort(arr) print(res)
мы получаем,[0 1 2 4 5 3]
что не так.arr[res]
выходыarray([ 1, 2, 3, 5, 9, 100])
, которые, кажется, совершенно нормально, так как этот результирующий массив находится в (возрастающем) порядке.arr=[1,2,3,100, 5, 9]
, я ожидаю, что результат будетinds=[0,1,2,5,3,4]
, потому что это порядок, в котором вы будете упорядочивать элементы (все чаще) - 1 находится на 0-м месте, 2 на 1-м месте, ...., 5 на 3 место и 9 место на 4 месте. Чтобы получить этот вывод (inds
), мне нужно запуститьargsort
дважды, как я уже упоминал.sort
, я считаю, что OP хочет другую функциональность, очень похожуюnp.argsort
на обычную (где можно использоватьarr[np.argsort[arr]]
отсортированный массив, как в последнем примере MATLAB). Ваш ответ относится к этому делу / вопросу вместо.Импортировать numpy как np
ДЛЯ ИНДЕКСА
argsort Возвращает индексы S в отсортированном порядке.
НА СТОИМОСТЬ
источник
Мы создадим еще один массив индексов от 0 до n-1. Затем заархивируем его в исходный массив и затем отсортируем его на основе исходных значений.
`
источник