Saya mencari untuk mengurutkan array sekitar 200-300 objek, mengurutkan pada kunci tertentu dan urutan tertentu (asc / desc). Urutan hasil harus konsisten dan stabil.
Apa algoritme terbaik untuk digunakan, dan dapatkah Anda memberikan contoh implementasinya dalam javascript?
Terima kasih!
javascript
algorithm
sorting
William Casarin
sumber
sumber
Jawaban:
Dimungkinkan untuk mendapatkan pengurutan yang stabil dari fungsi pengurutan yang tidak stabil.
Sebelum menyortir, Anda mendapatkan posisi semua elemen. Dalam kondisi pengurutan Anda, jika kedua elemen sama, maka Anda mengurutkan berdasarkan posisinya.
Tada! Anda punya jenis yang stabil.
Saya telah menulis artikel tentang itu di blog saya jika Anda ingin tahu lebih banyak tentang teknik ini dan cara menerapkannya: http://blog.vjeux.com/2010/javascript/javascript-sorting-table.html
sumber
Karena Anda mencari sesuatu yang stabil, jenis penggabungan harus dilakukan.
http://www.stoimen.com/blog/2010/07/02/friday-algorithms-javascript-merge-sort/
Kode dapat ditemukan di situs web di atas:
EDIT:
Menurut posting ini , sepertinya Array.Sort dalam beberapa implementasi menggunakan semacam gabungan.
sumber
Array#shift
mungkin bekerja dalam waktu O (n) dan begitu jugamerge
di O (n * n).Versi yang lebih pendek dari hal yang sama menggunakan fitur ES2017 seperti fungsi panah dan penghancuran:
Fungsi
Ini menerima array input dan membandingkan fungsi:
Ini juga mengembalikan array baru daripada membuat semacam di tempat seperti fungsi Array.sort () bawaan .
Uji
Jika kita mengambil
input
larik berikut , awalnya diurutkan berdasarkanweight
:Kemudian urutkan dengan
height
menggunakanstableSort
:Hasil dalam:
Namun mengurutkan
input
larik yang sama menggunakanArray.sort()
bawaan (di Chrome / NodeJS):Pengembalian:
Sumber daya
Memperbarui
sumber
stableSort
Fungsi merupakan solusi benar-benar hebat!Saya tahu bahwa pertanyaan ini telah dijawab untuk beberapa waktu, tetapi saya kebetulan memiliki implementasi penyortiran gabungan yang stabil untuk Array dan jQuery di clipboard saya, jadi saya akan membagikannya dengan harapan bahwa beberapa pencari di masa mendatang mungkin akan menganggapnya berguna.
Ini memungkinkan Anda untuk menentukan fungsi perbandingan Anda sendiri seperti biasanya
Array.sort
implementasi .Penerapan
Contoh Penggunaan
sumber
array.sort
, lihat pengujian di sini untuk string dan integer -> jsfiddle.net/QC64jmergeSort
dan tidaksort
, jadi tidak dimaksudkan sebagai pengganti pengganti. Terkadang Anda hanya memerlukan penyortiran gabungan yang stabil, misalnya saat mengurutkan tabel berdasarkan kolom.Anda dapat menggunakan polyfill berikut untuk mengimplementasikan pengurutan stabil apa pun penerapan aslinya, berdasarkan pernyataan yang dibuat dalam jawaban ini :
Menjalankan tes kinerja yang diterapkan di atas,
stableSort()
tampaknya berjalan pada sekitar 57% kecepatansort()
di Chrome versi 59-61.Penggunaan
.bind(compareFunction)
pada fungsi anonim yang dibungkus dalamstableSort()
meningkatkan kinerja relatif tersebut dari sekitar 38% dengan menghindari referensi cakupan yang tidak diperlukan kecompareFunction
pada setiap panggilan dengan menetapkannya ke konteks sebagai gantinya.Memperbarui
Mengubah operator terner menjadi korsleting logis, yang cenderung berkinerja lebih baik rata-rata (tampaknya membuat perbedaan efisiensi 2-3%).
sumber
Berikut ini mengurutkan array yang disediakan, dengan menerapkan fungsi bandingkan yang disediakan, mengembalikan perbandingan indeks asli saat fungsi bandingkan mengembalikan 0:
Contoh di bawah ini mengurutkan larik nama berdasarkan nama belakang, dengan mempertahankan urutan nama belakang yang sama:
sumber
jQuery.expando.split( "" ).sort( ( a, b ) => 0 ).join( "" ) === jQuery.expando
Berikut implementasi yang stabil. Ini berfungsi dengan menggunakan pengurutan asli, tetapi dalam kasus di mana elemen dibandingkan sama, Anda memutuskan hubungan menggunakan posisi indeks asli.
tes non-menyeluruh
jawaban lain menyinggung ini, tetapi tidak memposting codez.
Tapi, itu tidak cepat menurut patokan saya . Saya memodifikasi impl jenis gabungan untuk menerima fungsi komparator kustom, dan itu jauh lebih cepat.
sumber
Anda juga dapat menggunakan Timsort. Ini adalah algoritme yang sangat rumit (400+ baris, karenanya tidak ada kode sumber di sini), jadi lihat deskripsi Wikipedia atau gunakan salah satu implementasi JavaScript yang ada:
Implementasi GPL 3 . Dikemas sebagai Array.prototype.timsort. Tampaknya merupakan penulisan ulang kode Java yang tepat.
Implementasi domain publik Dimaksudkan sebagai tutorial, kode contoh hanya menunjukkan penggunaannya dengan bilangan bulat.
Timsort adalah hibrida yang sangat optimal dari mergesort dan shuffle sort dan merupakan algoritma pengurutan default di Python dan Java (1.7+). Ini adalah algoritme yang rumit, karena menggunakan algoritme berbeda untuk banyak kasus khusus. Tetapi sebagai hasilnya, ini sangat cepat dalam berbagai keadaan.
sumber
Sebuah mergeSort sederhana dari http://www.stoimen.com/blog/2010/07/02/friday-algorithms-javascript-merge-sort/
sumber
Saya harus mengurutkan array multidimensi dengan kolom arbitrer, dan kemudian dengan kolom lain. Saya menggunakan fungsi ini untuk mengurutkan:
Perhatikan bahwa ary.sort tidak pernah mengembalikan nol, yang mana beberapa implementasi fungsi "sort" membuat keputusan yang mungkin tidak tepat.
Ini juga sangat cepat.
sumber
Inilah cara Anda memperluas objek Array default JS dengan metode prototipe yang menggunakan MERGE SORT . Metode ini memungkinkan pengurutan pada kunci tertentu (parameter pertama) dan urutan tertentu ('asc' / 'desc' sebagai parameter kedua)
Anda dapat mengujinya sendiri dengan melepaskan cuplikan di atas ke konsol browser Anda, lalu mencoba:
Atau urutkan berdasarkan bidang tertentu dalam larik objek:
sumber
Jadi saya membutuhkan jenis yang stabil untuk aplikasi React + Redux saya, dan jawaban Vjeux di sini membantu saya. Namun, solusi (generik) saya tampaknya berbeda dari yang lain yang saya lihat sejauh ini, jadi saya membagikannya jika ada orang lain yang memiliki kasus penggunaan yang cocok:
sort()
API, di mana saya dapat mengirimkan fungsi komparator.Solusi saya adalah membuat array yang diketik
indices
, kemudian menggunakan fungsi perbandingan untuk mengurutkan ini indeks berdasarkan array yang akan diurutkan. Kemudian kita dapat menggunakanindices
sortir untuk mengurutkan larik asli atau membuat salinan terurut dalam sekali jalan. Jika itu membingungkan, pikirkan seperti ini: di mana Anda biasanya meneruskan fungsi perbandingan seperti:Anda sekarang menggunakan:
Kecepatan itu bagus; itu pada dasarnya adalah algoritma pengurutan built-in, ditambah dua lintasan linier pada akhirnya, dan satu lapisan tambahan dari overhead tipuan penunjuk.
Senang menerima umpan balik tentang pendekatan ini. Inilah implementasi lengkap saya:
sumber
Saya tahu ini sudah banyak dijawab. Saya hanya ingin melanjutkan posting implementasi TS cepat untuk siapa saja yang mendarat di sini mencari itu.
Metode ini tidak lagi berjalan di tempat, seperti yang dilakukan jenis asli. Saya juga ingin menunjukkan bahwa ini bukan yang paling efisien. Ia menambahkan dua loop dari urutan O (n). meskipun sort sendiri kemungkinan besar adalah O (n log (n)) jadi kurang dari itu.
Beberapa solusi yang disebutkan lebih berkinerja, berpikir ini mungkin kode yang lebih sedikit, juga menggunakan internal
Array.prototype.sort
.(Untuk solusi Javascript, cukup hapus semua jenis)
sumber
Menurut blog dev v8 dan caniuse.com
Array.sort
sudah stabil seperti yang dipersyaratkan oleh spek di browser modern, jadi Anda tidak perlu menggulung solusi Anda sendiri. Satu-satunya pengecualian yang bisa saya lihat adalah Edge, yang akan segera beralih ke chromium dan mendukungnya juga.sumber
sumber
Counting Sort lebih cepat daripada merge sort (ini bekerja dalam waktu O (n)) dan dimaksudkan untuk digunakan pada integer.
Contoh:
sumber
array [3, 1, 3]
hash ke[undefined, 1, undefined, 3]
. Kami mendapatkan dua nilai yang tidak ditentukan, sementara algoritme mengharapkan ada tiga di antaranya.