Saya tidak yakin ada banyak keuntungan untuk menyortir hash, kecuali jika Anda menggunakan eachatau each_pairmengulanginya. Bahkan kemudian, saya mungkin masih mengambil kunci, mengurutkannya, lalu beralih ke mereka mengambil nilai-nilai yang diperlukan. Itu memastikan kode akan berperilaku benar pada Rubi yang lebih lama.
the Tin Man
Masuk akal di ruby 1.9 juga. Saya memiliki koleksi janji yang dikelompokkan berdasarkan tanggal (sebagai kunci) yang berasal dari db dan saya secara manual diurutkan melalui ruby. Misalnya. {"2012-09-22": [...], "2012-09-30": [...], "2012-10-12": [...]}
Adit Saxena
Ya, saya menemukan proses Hash [h.sort] Anda lebih efektif daripada tombol pengurutan kemudian mengakses lagi hash melalui kunci yang diurutkan.
@zachaysan tetapi berhasil: h.sort{|a,z|a<=>z}.to_h(diuji 2.1.10, 2.3.3)
whitehat101
@ whitehat101 Anda benar. Saya memiliki bug ( aarray, bukan hanya kuncinya). Saya sudah menghapus komentar saya.
zachaysan
Hanya dalam kasus orang lain sedang mencari cara untuk mengurutkan array dari hash, ini akan melakukan trik (di mana h adalah array): h.map(&:sort).map(&:to_h).
JM Janzen
82
Catatan: Ruby> = 1.9.2 memiliki hash yang mempertahankan pesanan: kunci pesanan yang dimasukkan akan menjadi urutan yang disebutkan. Di bawah ini berlaku untuk versi yang lebih lama atau kode yang kompatibel dengan mundur.
Tidak ada konsep hash yang diurutkan. Jadi tidak, apa yang Anda lakukan tidak benar.
Jika Anda ingin diurutkan untuk ditampilkan, kembalikan string:
atau, jika Anda menginginkan kunci secara berurutan:
h.keys.sort
atau, jika Anda ingin mengakses elemen secara berurutan:
h.sort.map do|key,value|# keys will arrive in order to this block, with their associated value.end
tetapi secara ringkas, tidak masuk akal untuk berbicara tentang hash yang diurutkan. Dari dokumen , "Urutan di mana Anda melintasi hash dengan salah satu kunci atau nilai mungkin tampak sewenang-wenang, dan umumnya tidak akan berada dalam urutan penyisipan." Jadi memasukkan kunci dalam urutan tertentu ke dalam hash tidak akan membantu.
"Mulai 1.9.2 pesanan hash insert akan dipertahankan.", Dan itu manis.
the Tin Man
2
Re komentar pertama saya (merasa lucu): Misalnya, mengandalkan pemesanan hash akan secara diam-diam dan tidak terduga rusak untuk versi Ruby yang lebih tua dari 1.9.2.
Jo Liss
5
Bagaimana jawaban ini didapat sekitar 20 +1 tanpa menjawab satu pun dari dua bagian pertanyaan OP? "1) Apakah itu (contoh OP) menjadi cara terbaik untuk menyortir hash, 2) dan mengembalikan objek Hash"? Saya tidak iri pada +1's :) hanya setelah itu membaca jawaban saya masih memiliki pertanyaan asli. Juga jika intinya adalah bahwa tidak ada yang namanya hash yang disortir pada komentar untuk jawaban yang dipilih untuk pertanyaan ini stackoverflow.com/questions/489139/…
jj_
64
Saya selalu menggunakan sort_by. Anda perlu membungkus #sort_byoutput dengan Hash[]untuk membuatnya menghasilkan hash, jika tidak output array array. Atau, untuk mencapai ini, Anda dapat menjalankan #to_hmetode pada array tuple untuk mengubahnya menjadi k=>vstruktur (hash).
menggunakan sort_byhash akan mengembalikan array. Anda perlu memetakannya sebagai hash lagi. Hash[hsh.sort_by{|k,v| v}]
stevenspiel
1
ya, kelas enumerator mengartikan hash sebagai array saya pikir
boulder_ruby
3
Benar, sort adalah pada nilai-nilai: hsh.sort_by(&:last).to_h => {"b"=>10, "a"=>1000, "c"=>200000}.
Cary Swoveland
1
Perhatikan bahwa panggilan to_hhanya didukung di Ruby 2.1.0+
Phrogz
1
ada kesalahan ketik dalam komentar, koreksi:sort_by{|k,v| v}.to_h)
jitter
13
Tidak, bukan (Ruby 1.9.x)
require 'benchmark'
h ={"a"=>1,"c"=>3,"b"=>2,"d"=>4}
many =100_000
Benchmark.bm do|b|
GC.start
b.report("hash sort")do
many.times doHash[h.sort]endend
GC.start
b.report("keys sort")do
many.times do
nh ={}
h.keys.sort.each do|k|
nh[k]= h[k]endendendend
user system total real
hash sort 0.4000000.0000000.400000(0.405588)
keys sort 0.2500000.0100000.260000(0.260303)
Untuk perbedaan hash besar akan tumbuh hingga 10x dan lebih banyak
Anda memberikan jawaban terbaik untuk diri sendiri di OP: Hash[h.sort]Jika Anda menginginkan lebih banyak kemungkinan, berikut adalah modifikasi hash asli untuk membuatnya disortir:
Saya memperbaiki tautan untuk menunjuk ke Google kalau-kalau beberapa sejarawan ingin meneliti bagaimana ini bisa dilakukan di masa lalu. Tetapi siapa pun yang datang dengan ini sekarang harus menggunakan versi Ruby yang lebih baru.
@ peralatan adalah hash yang saya bangun di model saya dan kembali pada controller saya. Jika Anda memanggil .sort maka akan mengurutkan hash berdasarkan nilai kuncinya.
Saya membuat kelas mini, menyebutnya class AlphabeticalHash. Ini juga memiliki metode yang disebut ap, yang menerima satu argumen, sebuah Hash, sebagai masukan: ap variable. Akin to pp ( pp variable)
Tetapi ia akan (mencoba dan) mencetak dalam daftar abjad (kuncinya). Entah apakah ada orang lain yang ingin menggunakan ini, tersedia sebagai permata, Anda dapat menginstalnya seperti:gem install alphabetical_hash
Bagi saya, ini cukup sederhana. Jika orang lain membutuhkan lebih banyak fungsi, beri tahu saya, saya akan memasukkannya ke dalam permata.
EDIT: Kredit untuk Peter , yang memberi saya ide. :)
each
ataueach_pair
mengulanginya. Bahkan kemudian, saya mungkin masih mengambil kunci, mengurutkannya, lalu beralih ke mereka mengambil nilai-nilai yang diperlukan. Itu memastikan kode akan berperilaku benar pada Rubi yang lebih lama.Jawaban:
Di Ruby 2.1 itu sederhana:
sumber
h.sort{|a,z|a<=>z}.to_h
(diuji 2.1.10, 2.3.3)a
array, bukan hanya kuncinya). Saya sudah menghapus komentar saya.h.map(&:sort).map(&:to_h)
.Catatan: Ruby> = 1.9.2 memiliki hash yang mempertahankan pesanan: kunci pesanan yang dimasukkan akan menjadi urutan yang disebutkan. Di bawah ini berlaku untuk versi yang lebih lama atau kode yang kompatibel dengan mundur.
Tidak ada konsep hash yang diurutkan. Jadi tidak, apa yang Anda lakukan tidak benar.
Jika Anda ingin diurutkan untuk ditampilkan, kembalikan string:
atau, jika Anda menginginkan kunci secara berurutan:
atau, jika Anda ingin mengakses elemen secara berurutan:
tetapi secara ringkas, tidak masuk akal untuk berbicara tentang hash yang diurutkan. Dari dokumen , "Urutan di mana Anda melintasi hash dengan salah satu kunci atau nilai mungkin tampak sewenang-wenang, dan umumnya tidak akan berada dalam urutan penyisipan." Jadi memasukkan kunci dalam urutan tertentu ke dalam hash tidak akan membantu.
sumber
Saya selalu menggunakan
sort_by
. Anda perlu membungkus#sort_by
output denganHash[]
untuk membuatnya menghasilkan hash, jika tidak output array array. Atau, untuk mencapai ini, Anda dapat menjalankan#to_h
metode pada array tuple untuk mengubahnya menjadik=>v
struktur (hash).Ada pertanyaan serupa di " Bagaimana cara mengurutkan Ruby Hash berdasarkan nilai angka? ".
sumber
sort_by
hash akan mengembalikan array. Anda perlu memetakannya sebagai hash lagi.Hash[hsh.sort_by{|k,v| v}]
hsh.sort_by(&:last).to_h => {"b"=>10, "a"=>1000, "c"=>200000}
.to_h
hanya didukung di Ruby 2.1.0+sort_by{|k,v| v}.to_h)
Tidak, bukan (Ruby 1.9.x)
Untuk perbedaan hash besar akan tumbuh hingga 10x dan lebih banyak
sumber
Anda memberikan jawaban terbaik untuk diri sendiri di OP:
Hash[h.sort]
Jika Anda menginginkan lebih banyak kemungkinan, berikut adalah modifikasi hash asli untuk membuatnya disortir:sumber
Dengan penghancuran dan semacam Hash
Dihitung # sort_by
Hash # urutkan dengan perilaku default
Catatan: <Ruby 2.1
Catatan:> Ruby 2.1
sumber
v
Anda harushash.sort_by { |k, _v| k }.to_h
ActiveSupport :: OrderedHash adalah opsi lain jika Anda tidak ingin menggunakan ruby 1.9.2 atau memutar solusi Anda sendiri.
sumber
sumber
Saya memiliki masalah yang sama (saya harus menyortir peralatan saya dengan nama mereka) dan saya menyelesaikannya seperti ini:
@ peralatan adalah hash yang saya bangun di model saya dan kembali pada controller saya. Jika Anda memanggil .sort maka akan mengurutkan hash berdasarkan nilai kuncinya.
sumber
Saya menyukai solusinya di posting sebelumnya.
Saya membuat kelas mini, menyebutnya
class AlphabeticalHash
. Ini juga memiliki metode yang disebutap
, yang menerima satu argumen, sebuahHash
, sebagai masukan:ap variable
. Akin to pp (pp variable
)Tetapi ia akan (mencoba dan) mencetak dalam daftar abjad (kuncinya). Entah apakah ada orang lain yang ingin menggunakan ini, tersedia sebagai permata, Anda dapat menginstalnya seperti:
gem install alphabetical_hash
Bagi saya, ini cukup sederhana. Jika orang lain membutuhkan lebih banyak fungsi, beri tahu saya, saya akan memasukkannya ke dalam permata.
EDIT: Kredit untuk Peter , yang memberi saya ide. :)
sumber