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?

sts
sumber
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.

sepp2k
sumber
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
tomascharad
sumber
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
erik
sumber
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
glenn mcdonald
sumber
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.

Elie Teyssedou
sumber
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 .

MOPO3OB
sumber