Saya punya daftar angka:
myList = [1, 2, 3, 100, 5]
Sekarang jika saya mengurutkan daftar ini untuk mendapatkan [1, 2, 3, 5, 100]
. Yang saya inginkan adalah indeks elemen dari daftar asli dalam urutan yang diurutkan yaitu [0, 1, 2, 4, 3]
--- fungsi sortir MATLAB yang mengembalikan nilai dan indeks.
Jawaban:
Jika Anda menggunakan numpy, Anda memiliki fungsi argsort () yang tersedia:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html
Ini mengembalikan argumen yang akan mengurutkan array atau daftar.
sumber
Sesuatu seperti selanjutnya:
enumerate(myList)
memberi Anda daftar yang berisi tupel (indeks, nilai):Anda mengurutkan daftar dengan meneruskannya ke
sorted
dan menentukan fungsi untuk mengekstrak kunci pengurutan (elemen kedua dari setiap tuple; itulah gunanyalambda
. Akhirnya, indeks asli dari setiap elemen yang diurutkan diekstraksi menggunakan[i[0] for i in ...]
pemahaman daftar.sumber
itemgetter(1)
alih-alih fungsi lambdaitemgetter
fungsi dalamoperator
modul, FYI. Begitu jugafrom operator import itemgetter
untuk menggunakannya.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)
menghasilkan [1,2,0].sumber
Jawabannya
enumerate
bagus, tapi saya pribadi tidak suka lambda yang digunakan untuk mengurutkan berdasarkan nilainya. Berikut ini hanya membalikkan indeks dan nilai, dan mengurutkannya. Jadi pertama-tama akan mengurutkan berdasarkan nilai, kemudian berdasarkan indeks.sumber
Jawaban yang diperbarui dengan
enumerate
danitemgetter
:Zip daftar bersama-sama: Elemen pertama dalam tuple akan indeks, yang kedua adalah nilai (kemudian urutkan menggunakan nilai kedua tuple
x[1]
, x adalah tuple)Atau menggunakan
itemgetter
darioperator
modul`:sumber
Saya melakukan pemeriksaan kinerja cepat pada ini dengan perfplot (proyek saya) dan menemukan bahwa sulit untuk merekomendasikan hal lain selain numpy (perhatikan skala log):
Kode untuk mereproduksi plot:
sumber
Jika Anda tidak ingin menggunakan numpy,
tercepat, seperti yang ditunjukkan di sini .
sumber
Pada dasarnya Anda perlu melakukan
argsort
, implementasi apa yang Anda butuhkan tergantung jika Anda ingin menggunakan perpustakaan eksternal (misalnya NumPy) atau jika Anda ingin tetap murni-Python tanpa dependensi.Pertanyaan yang perlu Anda tanyakan pada diri sendiri adalah: Apakah Anda menginginkan
Sayangnya contoh dalam pertanyaan tidak menjelaskan apa yang diinginkan karena keduanya akan memberikan hasil yang sama:
Memilih
argsort
implementasinyaJika Anda memiliki NumPy yang Anda inginkan, Anda cukup menggunakan fungsi
numpy.argsort
atau metodenumpy.ndarray.argsort
.Implementasi tanpa NumPy telah disebutkan dalam beberapa jawaban lain, jadi saya akan rekap solusi tercepat sesuai dengan tolok ukur jawaban di sini
Mendapatkan indeks yang akan mengurutkan array / daftar
Untuk mendapatkan indeks yang akan mengurutkan array / daftar Anda cukup memanggil
argsort
array atau daftar. Saya menggunakan versi NumPy di sini tetapi implementasi Python harus memberikan hasil yang samaHasilnya berisi indeks yang diperlukan untuk mendapatkan array yang diurutkan.
Karena array yang diurutkan akan menjadi
[1, 2, 3, 4]
array yang diperdebatkan berisi indeks elemen-elemen ini dalam aslinya.1
dan berada pada indeks1
dalam dokumen asli sehingga elemen pertama dari hasilnya adalah1
.2
berada pada indeks2
dalam bahasa aslinya sehingga elemen kedua dari hasilnya adalah2
.3
berada pada indeks0
dalam bahasa aslinya sehingga elemen ketiga dari hasilnya adalah0
.4
dan berada pada indeks3
dalam dokumen asli sehingga elemen terakhir dari hasilnya adalah3
.Mendapatkan indeks yang akan dimiliki elemen-elemen dalam array / daftar yang diurutkan
Dalam hal ini, Anda perlu menerapkan
argsort
dua kali :Pada kasus ini :
3
, yang merupakan nilai terbesar ketiga sehingga akan memiliki indeks2
dalam array / daftar yang diurutkan sehingga elemen pertama adalah2
.1
, yang merupakan nilai terkecil sehingga akan memiliki indeks0
dalam array / daftar yang diurutkan sehingga elemen kedua adalah0
.2
, yang merupakan nilai terkecil kedua sehingga akan memiliki indeks1
dalam array yang diurutkan / daftar sehingga elemen ketiga adalah1
.4
yang merupakan nilai terbesar sehingga akan memiliki indeks3
dalam array / daftar yang diurutkan sehingga elemen terakhir adalah3
.sumber
Jawaban lainnya SALAH.
Berjalan
argsort
sekali bukanlah solusi. Misalnya, kode berikut:hasil
array([1, 2, 0], dtype=int64)
yang bukan apa yang kita inginkan.Jawabannya harus dijalankan
argsort
dua kali:memberi
array([2, 0, 1], dtype=int64)
seperti yang diharapkan.sumber
x[2]
(3) elemen terkecil, danx[1]
(1) elemen terbesar (sejak pengurutan integer memesannya dari nilai terkecil hingga nilai terbesar). Juga, dengan contoh OP, satunp.argsort([1, 2, 3, 100, 5])
hasilarray([0, 1, 2, 4, 3])
, yang tampaknya merupakan indeks yang diinginkan OP.arr = [1,2,3,100, 5, 9] res = np.argsort(arr) print(res)
maka kita mendapatkan[0 1 2 4 5 3]
yang salah.arr[res]
hasilarray([ 1, 2, 3, 5, 9, 100])
, yang tampaknya baik-baik saja, karena array yang dihasilkan dalam urutan (meningkat).arr=[1,2,3,100, 5, 9]
, saya mengharapkan output menjadiinds=[0,1,2,5,3,4]
, karena ini adalah urutan di mana Anda akan memesan elemen (semakin) - 1 di tempat 0s, 2 di tempat 1, ...., 5 di Juara 3 dan 9 Juara 4. Untuk mendapatkan output (inds
) saya harus menjalankanargsort
dua kali, seperti yang saya sebutkan.sort
, saya rasa OP menginginkan fungsionalitas lain, sepertinp.argsort
yang biasa digunakan (di mana orang dapat menggunakanarr[np.argsort[arr]]
untuk mendapatkan array yang diurutkan, seperti pada contoh MATLAB terakhir). Jawaban Anda berlaku untuk kasus / pertanyaan ini sebagai gantinya.Impor numpy sebagai np
UNTUK INDEKS
argsort Mengembalikan indeks S dalam urutan terurut
UNTUK NILAI
sumber
Kami akan membuat array indeks lain dari 0 hingga n-1. Kemudian pos ini ke array asli dan kemudian mengurutkannya berdasarkan nilai asli
`
sumber