Saya memiliki berbagai hash:
[
{ :foo => 'foo', :bar => 2 },
{ :foo => 'foo', :bar => 3 },
{ :foo => 'foo', :bar => 5 },
]
Saya mencoba untuk mengurutkan array ini dalam urutan menurun sesuai dengan nilai :bar
dalam setiap hash.
Saya menggunakan sort_by
untuk mengurutkan array di atas:
a.sort_by { |h| h[:bar] }
Namun, ini mengurutkan array dalam urutan menaik. Bagaimana cara membuatnya dalam urutan menurun?
Salah satu solusinya adalah melakukan hal berikut:
a.sort_by { |h| -h[:bar] }
Tetapi tanda negatif itu sepertinya tidak tepat.
sort_by.reverse
secara dramatis lebih efisien daripada jawaban yang saat ini diterima. Saya percaya ini juga lebih baik mengatasi masalah yang Anda sebutkan di atas untuk "menyampaikan maksud kode". Selain itu, Manusia Timah telah memperbarui jawabannya untuk versi ruby saat ini. Pertanyaan ini telah dilihat lebih dari 15 ribu kali. Jika Anda dapat menghemat bahkan 1 detik dari setiap waktu pemirsa, saya pikir itu sepadan.Jawaban:
Itu selalu mencerahkan untuk melakukan tolok ukur pada berbagai jawaban yang disarankan. Inilah yang saya temukan:
Saya pikir ini menarik bahwa @ Pablo's
sort_by{...}.reverse!
tercepat. Sebelum menjalankan tes saya pikir ini akan lebih lambat daripada "-a[:bar]
" tetapi meniadakan nilainya ternyata membutuhkan waktu lebih lama daripada membalik seluruh array dalam satu lintasan. Tidak banyak perbedaan, tetapi setiap percepatan kecil membantu.Berikut adalah hasil untuk Ruby 1.9.3p194 (2012-04-20 revisi 35410) [x86_64-darwin10.8.0]:
Ini ada di MacBook Pro lama. Mesin yang lebih baru, atau yang lebih cepat, akan memiliki nilai yang lebih rendah, tetapi perbedaan relatif akan tetap ada.
Berikut ini adalah versi yang sedikit diperbarui pada perangkat keras yang lebih baru dan versi 2.1.1 dari Ruby:
Hasil baru menjalankan kode di atas menggunakan Ruby 2.2.1 pada Macbook Pro yang lebih baru. Sekali lagi, angka pastinya tidak penting, ini adalah hubungan mereka:
Diperbarui untuk Ruby 2.7.1 pada Mid-2015 MacBook Pro:
Sumbernya
Array#reverse
adalah:do *p2-- = *p1++; while (--len > 0);
menyalin pointer ke elemen dalam urutan terbalik jika saya ingat C saya dengan benar, sehingga array dibalik.sumber
Hanya hal cepat, yang menunjukkan niat menurun.
(Akan memikirkan cara yang lebih baik untuk sementara waktu);)
sumber
Anda bisa melakukannya:
sumber
sort_by
adalah bahwa ia menghindari menjalankan fungsi perbandingan berkali-kalisort_by
jauh lebih efisien, dan lebih mudah dibaca. Meniadakan nilai atau melakukan pembalikan pada akhirnya akan lebih cepat dan lebih mudah dibaca.* -1
tidak bekerja dengan semua nilai (misalnya Waktu), danreverse
akan memesan ulang nilai yang diurutkan samaSaya melihat bahwa kita memiliki (di samping yang lain) pada dasarnya dua opsi:
dan
Meskipun kedua cara memberi Anda hasil yang sama ketika kunci penyortiran Anda unik, perlu diingat bahwa
reverse
cara tersebut akan membalik urutan tombol yang sama .Contoh:
Meskipun Anda sering tidak perlu peduli tentang ini, kadang-kadang Anda perlu peduli. Untuk menghindari perilaku seperti itu, Anda bisa memperkenalkan kunci penyortiran kedua (yang pasti harus unik setidaknya untuk semua item yang memiliki kunci penyortiran yang sama):
sumber
reverse
berbeda. Saya percaya ini juga akan mengacaukan jenis sebelumnya, dalam kasus di mana seseorang mencoba menerapkan beberapa jenis dalam urutan tertentu.Bagaimana dengan:
Berhasil!!
sumber
sort
akan berfungsi, itu hanya lebih cepat ketika menyortir nilai langsung. Jika Anda harus menggali untuk merekasort_by
lebih cepat. Lihat patokannya.Mengenai paket benchmark yang disebutkan, hasil ini juga berlaku untuk array yang diurutkan.
sort_by
/reverse
itu adalah:Dan hasilnya:
sumber
Solusi sederhana dari naik ke turun dan sebaliknya adalah:
STRING
DIGIT
sumber
Untuk orang-orang yang suka mengukur kecepatan dalam IPS;)
Dan hasil:
sumber