it-swarm.com.de

Wie bekomme ich eine bestimmte Ausgabe, die einen Hash in Ruby durchläuft?

Ich möchte eine bestimmte Ausgabe erhalten, bei der ein Ruby Hash.

Dies ist der Hash, über den ich iterieren möchte:

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

Dies ist die Ausgabe, die ich erhalten möchte:

1-----

a

b

2-----

c

3-----

d 

e

f

g

4-----

h

Wie kann ich in Ruby eine solche Ausgabe mit meinem Hash erhalten?

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

In Bezug auf die Reihenfolge sollte ich hinzufügen, dass die Elemente in 1.8 in zufälliger Reihenfolge iteriert werden (nun, tatsächlich in einer Reihenfolge, die durch die Hashing-Funktion von Fixnum definiert ist), während sie in 1.9 in der Reihenfolge des Literal iteriert werden.

312
sepp2k

Der einfachste Weg, einen Hash zu durchlaufen, ist folgender:

hash.each do |key, value|
  puts key
  puts value
end
81
tomascharad
hash.keys.sort.each do |key|
  puts "#{key}-----"
  hash[key].each { |val| puts val }
end
48
erik

Wenn Sie sort on a hash aufrufen, wird der Hash in verschachtelte Arrays konvertiert und anschließend nach Schlüsseln sortiert. Sie benötigen also nur Folgendes:

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

Und wenn Sie den "----" Teil nicht wirklich brauchen, kann es gerade sein:

puts h.sort
17
glenn mcdonald

Meine einzeilige Lösung:

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

Ich denke, es ist ziemlich einfach zu lesen.

9
Elie Teyssedou

Sie können auch verfeinernHash::each, Damit die Aufzählung rekursiv unterstützt wird. Hier ist meine Version von Hash::each (Hash::each_pair) Mit Block und Enumerator Unterstützung:

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

Hier ist die Verwendung Beispiele von Hash::each Mit und ohne recursive Flag:

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

Hier ist ein Beispiel aus der Frage selbst:

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

Schauen Sie sich auch meine rekursive Version von Hash::merge (Hash::merge!) hier an.

1
MOPO3OB