Ruby'de bir hash yineleyen belirli bir çıktı nasıl alınır?


218

Ruby Hash'i yineleyen belirli bir çıktı almak istiyorum.

Bu yineleme yapmak istediğiniz karma:

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

Bu almak istiyorum çıktıdır:

1-----

a

b

2-----

c

3-----

d 

e

f

g

4-----

h

Ruby'de Hash'imle nasıl böyle bir çıktı alabilirim?


3
Bir hash yineliyor ve sipariş edilmesini bekliyorsanız, muhtemelen başka bir koleksiyon türü kullanmanız gerekir
Allen Rice

karma değer radyo düğmesi seçeneği olarak geçebilir miyim ??
sts

hash radyo düğmesi seçeneği olarak geçiyorum .. ama ilk seçenek için radyo düğmesi alıyorum, diğer değerler için alamıyorum.
sts

1
@Allen: Hashes Ruby 1.9'da sipariş edildi. Rails ayrıca Ruby <1.9 üzerindeyken bir OrderedHash sağlar (yalnızca idareli kullanır). Bkz. Culann.com/2008/01/rails-goodies-activesupportorderedhash
James A. Rosen

Yanıtlar:


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

Eklemeliyim ki, 1.8'de öğeler rastgele sırayla (aslında Fixnum'un hash fonksiyonu tarafından tanımlanan bir sırayla) yinelenirken, 1.9'da değişmez sıraya göre yinelenecek.


1
anahtar hiçbir yerde kullanılmazsa ne olacak? . ?Anahtar yerine koymamız gerekir mi? örn .: |?, array|bu geçerli bir sözdizimi mi?
huzefa biyawarwala

1
@huzefabiyawarwala Hayır, ?Ruby'de geçerli bir değişken adı değil. Kullanabilirsin _ama kullanmana gerek yok.
sepp2k

2
@huzefabiyawarwala Evet, yazabilirsiniz|_, v|
sepp2k

1
v veya değer yerine değişken ad dizisini ne kullanır?
jrhicks

1
@jrhicks Çünkü OP değerleri diziler olan bir karmaya sahip.
Radon Rosborough

85

Bir karma üzerinden yinelemenin en temel yolu aşağıdaki gibidir:

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

Evet bu mantıklı. @ Sepp2k'in cevabının anahtarında neden # {} var?
committedandroider

Oh aldırma. Ben dize enterpolasyon için olduğunu gördü
committedandroider

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

18

Bir hash üzerinde sıralama çağırmak onu iç içe dizilere dönüştürür ve sonra onları anahtarla sıralar, böylece ihtiyacınız olan tek şey şu:

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

Ve aslında "----" kısmına ihtiyacınız yoksa, bu sadece şu olabilir:

puts h.sort

Karma anahtarlar sayıdır, bu nedenle '[k + "----"]' TypeError değerini yükseltir (String Fixnum'a zorlanamaz). '[K.to_s + "----"]' la ihtiyacınız var
glenn jackman

Yeterince doğru. Test versiyonumda harfler vardı. Daha da iyi olan "# {k} ----" kullanılarak düzeltildi.
glenn mcdonald

10

Tek satırlık çözümüm:

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

Bence okuması oldukça kolay.


1

Ayrıca , yinelemeli numaralandırmayı destekleyecek şekilde hassaslaştırabilirsiniz . İşte blok ve numaralandırıcı destekli ( ) sürümüm :Hash::eachHash::eachHash::each_pair

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

İşte kullanım olan örnekler arasında Hash::eacholan ve olmayan recursivebayrak:

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

İşte sorunun kendisinden bir örnek:

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"]

Ayrıca buradaHash::merge ( Hash::merge!) özyinelemeli sürümüne bir göz atın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.