Bagaimana cara mendapatkan output spesifik dengan menggunakan hash di Ruby?


218

Saya ingin mendapatkan hasil spesifik dengan mengulangi Ruby Hash.

Ini Hash yang ingin saya ulangi:

hash = {
  1 => ['a', 'b'], 
  2 => ['c'], 
  3 => ['d', 'e', 'f', 'g'], 
  4 => ['h']
}

Ini adalah output yang ingin saya dapatkan:

1-----

a

b

2-----

c

3-----

d 

e

f

g

4-----

h

Di Ruby, bagaimana saya bisa mendapatkan hasil seperti itu dengan Hash saya?


3
Jika Anda mengulangi hash dan mengharapkannya untuk dipesan, Anda mungkin perlu menggunakan beberapa jenis koleksi lainnya
Allen Rice

dapatkah saya melewatkan nilai hash sebagai opsi tombol radio ??
sts

Saya melewati hash sebagai opsi tombol radio .. tetapi untuk opsi pertama saya mendapatkan tombol radio, untuk nilai-nilai lain saya tidak mendapatkannya.
sts

1
@ Allen: Hash dipesan dalam Ruby 1.9. Rails juga menyediakan OrderedHash (yang hanya digunakan hemat) jika Anda menggunakan Ruby <1.9. Lihat culann.com/2008/01/rails-goodies-activesupportorderedhash
James A. Rosen

Jawaban:


323
hash.each do |key, array|
  puts "#{key}-----"
  puts array
end

Mengenai pesanan saya harus menambahkan, bahwa dalam 1,8 item akan diulang dalam urutan acak (well, sebenarnya dalam urutan yang didefinisikan oleh fungsi hashing Fixnum), sedangkan pada 1.9 akan diulang dalam urutan literal.


1
di sini bagaimana jika kunci tidak digunakan di mana pun? . Apakah kita perlu meletakkan ?kunci? mis: |?, array|apakah ini sintaks yang valid?
huzefa biyawarwala

1
@huzefabiyawarwala Tidak, ?bukan nama variabel yang valid di Ruby. Anda dapat menggunakan _, tetapi Anda tidak perlu melakukannya.
sepp2k

2
@huzefabiyawarwala Ya, Anda dapat menulis|_, v|
sepp2k

1
apa yang menggunakan array nama variabel, bukan v atau nilai?
jrhicks

1
@jrhicks Karena OP memiliki hash yang nilainya array.
Radon Rosborough

85

Cara paling dasar untuk beralih pada hash adalah sebagai berikut:

hash.each do |key, value|
  puts key
  puts value
end

Ya ini masuk akal. Mengapa jawaban @ sepp2k memiliki # {} di kunci?
berkomitmen dan

Oh ya sudah. Saya melihat bahwa itu untuk interpolasi string
berkomitmen dan

48
hash.keys.sort.each do |key|
  puts "#{key}-----"
  hash[key].each { |val| puts val }
end

18

Memanggil semacam pada hash mengubahnya menjadi array bersarang dan kemudian mengurutkannya dengan kunci, jadi yang Anda butuhkan adalah ini:

puts h.sort.map {|k,v| ["#{k}----"] + v}

Dan jika Anda tidak benar-benar membutuhkan bagian "----", itu bisa saja:

puts h.sort

Kunci hash adalah angka, jadi '[k + "----"]' memunculkan TypeError (String tidak dapat dipaksa ke dalam Fixnum). Anda perlu '[k.to_s + "----"]'
glenn jackman

Cukup benar. Saya memiliki surat dalam versi pengujian saya. Diperbaiki, menggunakan "# {k} ----" yang lebih baik.
glenn mcdonald

10

Solusi satu baris saya:

hash.each { |key, array| puts "#{key}-----", array }

Saya pikir ini cukup mudah dibaca.


1

Anda juga dapat memperbaiki Hash::each sehingga akan mendukung pencacahan rekursif . Ini adalah versi saya Hash::each( Hash::each_pair) dengan dukungan blok dan enumerator :

module HashRecursive
    refine Hash do
        def each(recursive=false, &block)
            if recursive
                Enumerator.new do |yielder|
                    self.map do |key, value|
                        value.each(recursive=true).map{ |key_next, value_next| yielder << [[key, key_next].flatten, value_next] } if value.is_a?(Hash)
                        yielder << [[key], value]
                    end
                end.entries.each(&block)
            else
                super(&block)
            end
        end
        alias_method(:each_pair, :each)
    end
end

using HashRecursive

Berikut adalah penggunaan contoh dari Hash::eachdengan dan tanpa recursivebendera:

hash = {
    :a => {
        :b => {
            :c => 1,
            :d => [2, 3, 4]
        },
        :e => 5
    },
    :f => 6
}

p hash.each, hash.each {}, hash.each.size
# #<Enumerator: {:a=>{:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}, :f=>6}:each>
# {:a=>{:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}, :f=>6}
# 2

p hash.each(true), hash.each(true) {}, hash.each(true).size
# #<Enumerator: [[[:a, :b, :c], 1], [[:a, :b, :d], [2, 3, 4]], [[:a, :b], {:c=>1, :d=>[2, 3, 4]}], [[:a, :e], 5], [[:a], {:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}], [[:f], 6]]:each>
# [[[:a, :b, :c], 1], [[:a, :b, :d], [2, 3, 4]], [[:a, :b], {:c=>1, :d=>[2, 3, 4]}], [[:a, :e], 5], [[:a], {:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}], [[:f], 6]]
# 6

hash.each do |key, value|
    puts "#{key} => #{value}"
end
# a => {:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}
# f => 6

hash.each(true) do |key, value|
    puts "#{key} => #{value}"
end
# [:a, :b, :c] => 1
# [:a, :b, :d] => [2, 3, 4]
# [:a, :b] => {:c=>1, :d=>[2, 3, 4]}
# [:a, :e] => 5
# [:a] => {:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}
# [:f] => 6

hash.each_pair(recursive=true) do |key, value|
    puts "#{key} => #{value}" unless value.is_a?(Hash)
end
# [:a, :b, :c] => 1
# [:a, :b, :d] => [2, 3, 4]
# [:a, :e] => 5
# [:f] => 6

Ini adalah contoh dari pertanyaan itu sendiri:

hash = {
    1   =>  ["a", "b"], 
    2   =>  ["c"], 
    3   =>  ["a", "d", "f", "g"], 
    4   =>  ["q"]
}

hash.each(recursive=false) do |key, value|
    puts "#{key} => #{value}"
end
# 1 => ["a", "b"]
# 2 => ["c"]
# 3 => ["a", "d", "f", "g"]
# 4 => ["q"]

Lihat juga versi rekursif saya Hash::merge( Hash::merge!) di sini .

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.