Katakanlah saya memiliki dua daftar:
list1 = [3, 2, 4, 1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']
Jika saya menjalankan list1.sort()
, itu akan mengurutkannya [1,1,2,3,4]
tetapi apakah ada cara untuk list2
menyinkronkan juga (jadi saya dapat mengatakan item 4
milik 'three'
)? Jadi, keluaran yang diharapkan adalah:
list1 = [1, 1, 2, 3, 4]
list2 = ['one', 'one2', 'two', 'three', 'four']
Masalah saya adalah saya memiliki program yang cukup kompleks yang berfungsi dengan baik dengan daftar tetapi saya perlu mulai mereferensikan beberapa data. Saya tahu ini adalah situasi yang sempurna untuk kamus tetapi saya mencoba menghindari kamus dalam pemrosesan saya karena saya perlu mengurutkan nilai-nilai kunci (jika saya harus menggunakan kamus, saya tahu cara menggunakannya).
Pada dasarnya sifat dari program ini adalah, data datang dalam urutan acak (seperti di atas), saya perlu menyortirnya, memprosesnya dan kemudian mengirimkan hasilnya (urutan tidak masalah tetapi pengguna harus tahu hasil mana yang termasuk kunci). Saya berpikir untuk meletakkannya di kamus terlebih dahulu, lalu menyortir daftar satu tetapi saya tidak akan memiliki cara untuk membedakan item dengan nilai yang sama jika urutan tidak dipertahankan (mungkin berdampak saat mengkomunikasikan hasil kepada pengguna). Idealnya, setelah saya mendapatkan daftar tersebut, saya lebih suka mencari cara untuk menyortir kedua daftar tersebut. Apakah ini mungkin?
Jawaban:
Satu pendekatan klasik untuk masalah ini adalah menggunakan idiom "menghias, mengurutkan, tidak mendekorasi", yang sangat sederhana menggunakan
zip
fungsi bawaan python :>>> list1 = [3,2,4,1, 1] >>> list2 = ['three', 'two', 'four', 'one', 'one2'] >>> list1, list2 = zip(*sorted(zip(list1, list2))) >>> list1 (1, 1, 2, 3, 4) >>> list2 ('one', 'one2', 'two', 'three', 'four')
Ini tentu saja bukan lagi daftar, tetapi itu mudah diperbaiki, jika penting:
>>> list1, list2 = (list(t) for t in zip(*sorted(zip(list1, list2)))) >>> list1 [1, 1, 2, 3, 4] >>> list2 ['one', 'one2', 'two', 'three', 'four']
Perlu dicatat bahwa hal di atas mungkin mengorbankan kecepatan demi kesederhanaan; versi di tempat, yang membutuhkan 3 baris, sedikit lebih cepat di mesin saya untuk daftar kecil:
>>> %timeit zip(*sorted(zip(list1, list2))) 100000 loops, best of 3: 3.3 us per loop >>> %timeit tups = zip(list1, list2); tups.sort(); zip(*tups) 100000 loops, best of 3: 2.84 us per loop
Sebaliknya, untuk daftar yang lebih besar, versi satu baris bisa lebih cepat:
>>> %timeit zip(*sorted(zip(list1, list2))) 100 loops, best of 3: 8.09 ms per loop >>> %timeit tups = zip(list1, list2); tups.sort(); zip(*tups) 100 loops, best of 3: 8.51 ms per loop
Seperti yang ditunjukkan Quantum7, saran JSF masih sedikit lebih cepat, tetapi mungkin hanya akan sedikit lebih cepat, karena Python menggunakan idiom DSU yang sama secara internal untuk semua jenis berbasis kunci. Itu hanya terjadi sedikit lebih dekat dengan logam telanjang. (Ini menunjukkan seberapa baik
zip
rutinitas yang dioptimalkan !)Saya pikir
zip
pendekatan berbasis lebih fleksibel dan sedikit lebih mudah dibaca, jadi saya lebih suka.sumber
*
operator melakukan pembongkaran argumen ,zip(*x)
memiliki properti menarik yang merupakan kebalikannya:l = [(1, 2), (3, 4)]; list(zip(*zip(*l))) == l
returnTrue
. Ini secara efektif merupakan operator transposisi.zip()
sendiri hanyalah operator yang sama, tetapi mengasumsikan bahwa Anda telah membongkar urutan input secara manual.Anda dapat mengurutkan indeks menggunakan nilai sebagai kunci:
Untuk mendapatkan daftar yang diurutkan diberikan indeks yang diurutkan:
Dalam kasus Anda, Anda tidak boleh memiliki
list1
,list2
melainkan satu daftar pasangan:data = [(3, 'three'), (2, 'two'), (4, 'four'), (1, 'one'), (1, 'one2')]
Mudah dibuat; mudah untuk mengurutkan dengan Python:
data.sort() # sort using a pair as a key
Urutkan hanya berdasarkan nilai pertama:
data.sort(key=lambda pair: pair[0])
sumber
list()
berkelilingmap()
jika Anda ingin menggunakan kode ini dengan Python 3.sorted_list1 = list(map(list1.__getitem__, indexes))
seseorang bisa melakukannyasorted_list1 = [list1[i] for i in indexes]
.Saya telah menggunakan jawaban yang diberikan oleh pengirim untuk waktu yang lama sampai saya menemukannya
np.argsort
. Berikut cara kerjanya.# idx works on np.array and not lists. list1 = np.array([3,2,4,1]) list2 = np.array(["three","two","four","one"]) idx = np.argsort(list1) list1 = np.array(list1)[idx] list2 = np.array(list2)[idx]
Saya menemukan solusi ini lebih intuitif, dan bekerja dengan sangat baik. Performa:
def sorting(l1, l2): # l1 and l2 has to be numpy arrays idx = np.argsort(l1) return l1[idx], l2[idx] # list1 and list2 are np.arrays here... %timeit sorting(list1, list2) 100000 loops, best of 3: 3.53 us per loop # This works best when the lists are NOT np.array %timeit zip(*sorted(zip(list1, list2))) 100000 loops, best of 3: 2.41 us per loop # 0.01us better for np.array (I think this is negligible) %timeit tups = zip(list1, list2); tups.sort(); zip(*tups) 100000 loops, best for 3 loops: 1.96 us per loop
Meskipun
np.argsort
bukan yang tercepat, saya merasa lebih mudah digunakan.sumber
TypeError: only integer arrays with one element can be converted to an index
(Python 2.7.6, numpy 1.8.2). Untuk memperbaikinya, list1 dan list2 harus dideklarasikan sebagai array numpy.np.argsort
tidak mencoba mengubahnya menjadi secaranp.array
internal.Transformasi Schwartzian . Penyortiran Python bawaan stabil, jadi keduanya
1
tidak menimbulkan masalah.>>> l1 = [3, 2, 4, 1, 1] >>> l2 = ['three', 'two', 'four', 'one', 'second one'] >>> zip(*sorted(zip(l1, l2))) [(1, 1, 2, 3, 4), ('one', 'second one', 'two', 'three', 'four')]
sumber
Anda dapat menggunakan fungsi
zip()
dansort()
untuk melakukannya:Python 2.6.5 (r265:79063, Jun 12 2010, 17:07:01) [GCC 4.3.4 20090804 (release) 1] on cygwin >>> list1 = [3,2,4,1,1] >>> list2 = ['three', 'two', 'four', 'one', 'one2'] >>> zipped = zip(list1, list2) >>> zipped.sort() >>> slist1 = [i for (i, s) in zipped] >>> slist1 [1, 1, 2, 3, 4] >>> slist2 = [s for (i, s) in zipped] >>> slist2 ['one', 'one2', 'two', 'three', 'four']
Semoga ini membantu
sumber
Bagaimana dengan:
list1 = [3,2,4,1, 1] list2 = ['three', 'two', 'four', 'one', 'one2'] sortedRes = sorted(zip(list1, list2), key=lambda x: x[0]) # use 0 or 1 depending on what you want to sort >>> [(1, 'one'), (1, 'one2'), (2, 'two'), (3, 'three'), (4, 'four')]
sumber
Salah satu caranya adalah melacak kemana setiap indeks pergi dengan menyortir identitas [0,1,2, .. n]
Ini berfungsi untuk sejumlah daftar.
Kemudian pindahkan setiap item ke posisinya. Menggunakan sambungan adalah yang terbaik.
list1 = [3,2,4,1, 1] list2 = ['three', 'two', 'four', 'one', 'one2'] index = list(range(len(list1))) print(index) '[0, 1, 2, 3, 4]' index.sort(key = list1.__getitem__) print(index) '[3, 4, 1, 0, 2]' list1[:] = [list1[i] for i in index] list2[:] = [list2[i] for i in index] print(list1) print(list2) '[1, 1, 2, 3, 4]' "['one', 'one2', 'two', 'three', 'four']"
Perhatikan bahwa kami dapat mengulang daftar tanpa menyortirnya:
list1_iter = (list1[i] for i in index)
sumber
Anda bisa menggunakan argumen kunci dalam metode sort () kecuali Anda memiliki dua nilai yang sama dalam list2.
Kode diberikan di bawah ini:
sorted(list2, key = lambda x: list1[list2.index(x)])
Ini mengurutkan list2 sesuai dengan nilai yang sesuai di list1, tetapi pastikan bahwa saat menggunakan ini, tidak ada dua nilai dalam list2 yang dievaluasi sama karena fungsi list.index () memberikan nilai pertama
sumber
Jika Anda menggunakan numpy, Anda dapat menggunakan
np.argsort
untuk mendapatkan indeks yang diurutkan dan menerapkan indeks tersebut ke daftar. Ini berfungsi untuk sejumlah daftar yang ingin Anda urutkan.import numpy as np arr1 = np.array([4,3,1,32,21]) arr2 = arr1 * 10 sorted_idxs = np.argsort(arr1) print(sorted_idxs) >>> array([2, 1, 0, 4, 3]) print(arr1[sorted_idxs]) >>> array([ 1, 3, 4, 21, 32]) print(arr2[sorted_idxs]) >>> array([ 10, 30, 40, 210, 320])
sumber
solusi algoritmik:
list1 = [3,2,4,1, 1] list2 = ['three', 'two', 'four', 'one', 'one2'] lis = [(list1[i], list2[i]) for i in range(len(list1))] list1.sort() list2 = [x[1] for i in range(len(list1)) for x in lis if x[0] == i]
Keluaran:
->
Kecepatan keluaran:0.2s
>>>list1 >>>[1, 1, 2, 3, 4] >>>list2 >>>['one', 'one2', 'two', 'three', 'four']
sumber
Pendekatan lain untuk mempertahankan urutan daftar string saat menyortir daftar lain adalah sebagai berikut:
list1 = [3,2,4,1, 1] list2 = ['three', 'two', 'four', 'one', 'one2'] # sort on list1 while retaining order of string list sorted_list1 = [y for _,y in sorted(zip(list1,list2),key=lambda x: x[0])] sorted_list2 = sorted(list1) print(sorted_list1) print(sorted_list2)
keluaran
['one', 'one2', 'two', 'three', 'four'] [1, 1, 2, 3, 4]
sumber
Saya ingin memperluas jawaban open jfs , yang bekerja dengan baik untuk masalah saya: mengurutkan dua daftar dengan daftar ketiga yang dihias :
Kita dapat membuat daftar yang didekorasi dengan cara apa pun, tetapi dalam hal ini kita akan membuatnya dari elemen salah satu dari dua daftar asli, yang ingin kita urutkan:
# say we have the following list and we want to sort both by the algorithms name # (if we were to sort by the string_list, it would sort by the numerical # value in the strings) string_list = ["0.123 Algo. XYZ", "0.345 Algo. BCD", "0.987 Algo. ABC"] dict_list = [{"dict_xyz": "XYZ"}, {"dict_bcd": "BCD"}, {"dict_abc": "ABC"}] # thus we need to create the decorator list, which we can now use to sort decorated = [text[6:] for text in string_list] # decorated list to sort >>> decorated ['Algo. XYZ', 'Algo. BCD', 'Algo. ABC']
Sekarang kita dapat menerapkan solusi jfs untuk mengurutkan kedua daftar kita menurut yang ketiga
# create and sort the list of indices sorted_indices = list(range(len(string_list))) sorted_indices.sort(key=decorated.__getitem__) # map sorted indices to the two, original lists sorted_stringList = list(map(string_list.__getitem__, sorted_indices)) sorted_dictList = list(map(dict_list.__getitem__, sorted_indices)) # output >>> sorted_stringList ['0.987 Algo. ABC', '0.345 Algo. BCD', '0.123 Algo. XYZ'] >>> sorted_dictList [{'dict_abc': 'ABC'}, {'dict_bcd': 'BCD'}, {'dict_xyz': 'XYZ'}]
Sunting: Hai teman-teman, saya membuat posting blok tentang ini, periksa jika Anda menyukainya :) 🐍🐍🐍
sumber
newsource=[];newtarget=[] for valueT in targetFiles: for valueS in sourceFiles: l1=len(valueS);l2=len(valueT); j=0 while (j< l1): if (str(valueT) == valueS[j:l1]) : newsource.append(valueS) newtarget.append(valueT) j+=1
sumber