it-swarm-id.com

bagaimana cara mengembalikan indeks daftar yang diurutkan?

Saya perlu mengurutkan daftar dan kemudian mengembalikan daftar dengan indeks item yang diurutkan dalam daftar. Misalnya, jika daftar yang ingin saya urutkan adalah [2,3,1,4,5], saya perlu [2,0,1,3,4] untuk dikembalikan.

Pertanyaan ini diposting pada byte, tetapi saya pikir saya akan memposting ulang di sini. http://bytes.com/topic/python/answers/44513-sorting-list-then-return-index-sorted-item

Kebutuhan spesifik saya untuk mengurutkan daftar objek berdasarkan properti dari objek. Saya kemudian perlu memesan ulang daftar yang sesuai agar sesuai dengan urutan daftar yang baru disortir.

Apakah ada cara yang baik untuk melakukan ini?

102
alex

Anda dapat menggunakan parameter python sorting functions 'key untuk mengurutkan array indeks.

>>> s = [2, 3, 1, 4, 5]
>>> sorted(range(len(s)), key=lambda k: s[k])
[2, 0, 1, 3, 4]
>>> 
191
sykora

Anda dapat melakukan ini dengan metode numpy's argsort jika Anda memiliki numpy yang tersedia:

>>> import numpy
>>> vals = numpy.array([2,3,1,4,5])
>>> vals
array([2, 3, 1, 4, 5])
>>> sort_index = numpy.argsort(vals)
>>> sort_index
array([2, 0, 1, 3, 4])

Jika tidak tersedia, diambil dari pertanyaan ini , ini adalah metode tercepat:

>>> vals = [2,3,1,4,5]
>>> sorted(range(len(vals)), key=vals.__getitem__)
[2, 0, 1, 3, 4]
65
jterrace

Jika Anda membutuhkan daftar yang diurutkan dan daftar indeks, Anda dapat melakukan:

>>> L = [2,3,1,4,5]
>>> from operator import itemgetter
>>> indices, L_sorted = Zip(*sorted(enumerate(L), key=itemgetter(1)))
>>> list(L_sorted)
[1, 2, 3, 4, 5]
>>> list(indices)
[2, 0, 1, 3, 4]

Atau, untuk Python <2.4 (tidak ada itemgetter atau sorted):

>>> temp = [(v,i) for i,v in enumerate(L)]
>>> temp.sort
>>> indices, L_sorted = Zip(*temp)

hal. Idom Zip(*iterable) membalikkan proses Zip (unzip).


Memperbarui:

Untuk menangani persyaratan spesifik Anda:

"Kebutuhan spesifik saya untuk mengurutkan daftar objek berdasarkan pada properti objek. Saya kemudian perlu memesan ulang daftar yang sesuai untuk mencocokkan urutan daftar yang baru disortir."

Itu cara bertele-tele untuk melakukannya. Anda bisa mencapainya dengan satu pengurutan dengan zip kedua daftar bersama lalu mengurutkan menggunakan properti objek sebagai kunci pengurutan Anda (dan unzipping setelah).

zipped = Zip(obj_list, secondary_list)
zipped_sorted = sorted(combined, key=lambda x: x[0].some_obj_attribute)
obj_list, secondary_list = map(list, Zip(*zipped_sorted))

Berikut ini contoh sederhana, menggunakan string untuk mewakili objek Anda. Di sini kita menggunakan panjang string sebagai kunci untuk menyortir .:

>>> str_list = ["banana", "Apple", "nom", "Eeeeeeeeeeek"]
>>> sec_list = [0.123423, 9.231, 23, 10.11001]
>>> temp = sorted(Zip(str_list, sec_list), key=lambda x: len(x[0]))
>>> str_list, sec_list = map(list, Zip(*temp))
>>> str_list
['nom', 'Apple', 'banana', 'Eeeeeeeeeeek']
>>> sec_list
[23, 9.231, 0.123423, 10.11001]
12
Shawn Chin

Bagaimana tentang

l1 = [2,3,1,4,5]
l2 = [l1.index(x) for x in sorted(l1)]
7
sizzzzlerz

anda dapat menggunakan numpy.argsort

atau kamu bisa melakukan:

test =  [2,3,1,4,5]
idxs = list(Zip(*sorted([(val, i) for i, val in enumerate(test)])))[1]

Zip akan rearange daftar sehingga elemen pertama adalah test dan yang kedua adalah idxs.

1
Simon Bergot

Apa yang akan saya lakukan, dengan melihat kebutuhan spesifik Anda:

Katakanlah Anda memiliki daftar a dengan beberapa nilai, dan kunci Anda ada dalam atribut x dari objek yang disimpan dalam daftar b

keys = {i:j.x for i,j in Zip(a, b)}
a.sort(key=keys.__get_item__)

Dengan metode ini Anda mendapatkan daftar Anda dipesan tanpa harus membangun daftar permutasi menengah yang Anda minta.

0
fortran