Mam listę numeryczną:
myList = [1, 2, 3, 100, 5]
Teraz posortuję tę listę, aby uzyskać [1, 2, 3, 5, 100]
. To, czego chcę, to indeksy elementów z oryginalnej listy w posortowanej kolejności, tj. [0, 1, 2, 4, 3]
--- ala funkcja sortująca MATLAB, która zwraca zarówno wartości, jak i indeksy.
Odpowiedzi:
Jeśli używasz numpy, masz dostępną funkcję argsort ():
http://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html
Zwraca argumenty, które posortowałyby tablicę lub listę.
źródło
Coś jak następne:
enumerate(myList)
daje listę zawierającą krotki (indeks, wartość):Sortujesz listę, przekazując ją
sorted
i określając funkcję do wyodrębnienia klucza sortowania (drugi element każdej krotki; po tolambda
jest. Na koniec oryginalny indeks każdego posortowanego elementu jest wyodrębniany przy użyciu[i[0] for i in ...]
listy.źródło
itemgetter(1)
zamiast funkcji lambdaitemgetter
funkcji woperator
module, FYI. Więc zrób to,from operator import itemgetter
aby z niego skorzystać.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)
daje [1,2,0].źródło
Odpowiedzi
enumerate
są miłe, ale osobiście nie lubię lambda używanego do sortowania według wartości. Poniższe odwraca indeks i wartość i sortuje je. Więc najpierw posortuje według wartości, a następnie według indeksu.źródło
Zaktualizowana odpowiedź za pomocą
enumerate
iitemgetter
:Spakuj listy razem: pierwszy element w krotce będzie indeksem, drugi to wartość (następnie posortuj go przy użyciu drugiej wartości krotki
x[1]
, x to krotka)Lub używając
itemgetter
zoperator
modułu`:źródło
Zrobiłem szybką kontrolę wydajności tych przy pomocy perfplot (mój projekt) i stwierdziłem, że trudno jest polecić cokolwiek innego niż numpy (zwróć uwagę na skalę logów):
Kod do odtworzenia fabuły:
źródło
Jeśli nie chcesz używać numpy,
jest najszybszy, jak pokazano tutaj .
źródło
Zasadniczo musisz zrobić
argsort
, to jakiej implementacji potrzebujesz, jeśli chcesz korzystać z zewnętrznych bibliotek (np. NumPy) lub jeśli chcesz pozostać czystym Pythonem bez zależności.Pytanie, które musisz sobie zadać, brzmi: czy chcesz
Niestety przykład w pytaniu nie wyjaśnia, co jest pożądane, ponieważ oba dają ten sam rezultat:
Wybierając
argsort
implementacjiJeśli masz do dyspozycji NumPy, możesz po prostu użyć funkcji
numpy.argsort
lub metodynumpy.ndarray.argsort
.Wdrożenie bez NumPy zostało już wspomniane w kilku innych odpowiedziach, więc po prostu podsumuję najszybsze rozwiązanie zgodnie z odpowiedzią testu porównawczego tutaj
Uzyskiwanie wskaźników, które posortowałyby tablicę / listę
Aby uzyskać indeksy, które posortowałyby tablicę / listę, możesz po prostu wywołać
argsort
tablicę lub listę. Używam tutaj wersji NumPy, ale implementacja Pythona powinna dawać takie same wynikiWynik zawiera indeksy potrzebne do uzyskania posortowanej tablicy.
Ponieważ posortowana tablica byłaby tablicą
[1, 2, 3, 4]
argsortowaną, zawiera indeksy tych elementów w oryginale.1
i jest w indeksie1
w oryginale, więc pierwszym elementem wyniku jest1
.2
Jest indeksem2
w oryginale więc drugi element wyniku jest2
.3
Jest indeksem0
w oryginale więc trzeci element wyniku jest0
.4
i jest w indeksie3
w oryginale, więc ostatnim elementem wyniku jest3
.Uzyskiwanie indeksów, które elementy miałyby w posortowanej tablicy / liście
W takim przypadku należy złożyć
argsort
dwukrotnie wniosek :W tym przypadku :
3
, co jest trzecią co do wielkości wartością, więc miałby indeks2
w posortowanej tablicy / liście, więc pierwszym elementem jest2
.1
, która jest najmniejszą wartością, więc miałby indeks0
w posortowanej tablicy / liście, więc drugim elementem jest0
.2
, co jest drugą najmniejszą wartością, więc miałby indeks1
w posortowanej tablicy / liście, więc trzeci element to1
.4
największa wartość, więc miałby indeks3
w posortowanej tablicy / liście, więc ostatnim elementem jest3
.źródło
Inne odpowiedzi są NIEPRAWIDŁOWE.
Uruchamianie
argsort
raz nie jest rozwiązaniem. Na przykład następujący kod:plony,
array([1, 2, 0], dtype=int64)
których nie chcemy.Odpowiedź powinna brzmieć
argsort
dwa razy:daje
array([2, 0, 1], dtype=int64)
zgodnie z oczekiwaniami.źródło
x[2]
(3) najmniejszym elementem ix[1]
(1) największym elementem (ponieważ sortowanie liczb całkowitych porządkuje je od najmniejszej wartości do największej wartości). Ponadto, na przykładzie PO, pojedynczynp.argsort([1, 2, 3, 100, 5])
dochódarray([0, 1, 2, 4, 3])
, który wydaje się być wskaźnikami, których chce PO.arr = [1,2,3,100, 5, 9] res = np.argsort(arr) print(res)
, dostaniemy[0 1 2 4 5 3]
co jest złe.arr[res]
dajearray([ 1, 2, 3, 5, 9, 100])
, co wydaje się być całkowicie w porządku, ponieważ wynikowa tablica jest w (rosnącej) kolejności.arr=[1,2,3,100, 5, 9]
, oczekuję, że wynik będzieinds=[0,1,2,5,3,4]
, ponieważ jest to kolejność, w której będziesz porządkować elementy (coraz częściej) - 1 jest na miejscu 0, 2 na 1 miejscu, ...., 5 na 3 miejsce i 9 na 4 miejscu. Aby uzyskać ten wynik (inds
), muszę uruchomićargsort
dwa razy, jak już wspomniałem.sort
, sądzę, że OP chce innej funkcjonalności, podobnie jaknp.argsort
zwykle jest używana (gdzie można użyćarr[np.argsort[arr]]
do uzyskania posortowanej tablicy, jak w ostatnim przykładzie MATLAB). Twoja odpowiedź dotyczy tej sprawy / pytania .Zaimportuj numpy jako np
DLA INDEKSU
argsort Zwraca indeksy S w posortowanej kolejności
DLA WARTOŚCI
źródło
Utworzymy kolejną tablicę indeksów od 0 do n-1, następnie spakujemy ją do oryginalnej tablicy, a następnie posortujemy na podstawie oryginalnych wartości
`
źródło