Je veux obtenir une sortie spécifique itérant un Ruby Hash.
Voici le hachage sur lequel je veux parcourir:
hash = {
1 => ['a', 'b'],
2 => ['c'],
3 => ['d', 'e', 'f', 'g'],
4 => ['h']
}
Voici le résultat que j'aimerais obtenir:
1-----
a
b
2-----
c
3-----
d
e
f
g
4-----
h
En Ruby, comment puis-je obtenir une telle sortie avec mon hachage?
hash.each do |key, array|
puts "#{key}-----"
puts array
end
En ce qui concerne l’ordre, j’ajouterai que dans la version 1.8, les éléments seront itérés dans un ordre aléatoire (en fait, dans un ordre défini par la fonction de hachage de Fixnum), alors que dans la version 1.9, ils seront itérés dans l’ordre du littéral.
Le moyen le plus simple d'itérer sur un hachage est le suivant:
hash.each do |key, value|
puts key
puts value
end
hash.keys.sort.each do |key|
puts "#{key}-----"
hash[key].each { |val| puts val }
end
L'appel d'un tri sur un hachage le convertit en tableaux imbriqués, puis les trie par clé. Vous n'avez donc besoin que de ceci:
puts h.sort.map {|k,v| ["#{k}----"] + v}
Et si vous n'avez pas réellement besoin de la partie "----", cela peut simplement être:
puts h.sort
Ma solution en une seule ligne:
hash.each { |key, array| puts "#{key}-----", array }
Je pense que c'est assez facile à lire.
Vous pouvez également raffiner Hash::each
afin qu'il prenne en charge récursif énumération. Voici ma version de Hash::each
(Hash::each_pair
) avec bloc et énumérateur support:
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
Voici des exemples d'utilisation de Hash::each
avec et sans 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
Voici un exemple tiré de la question elle-même:
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"]
Jetez également un coup d'œil à ma version récursive de Hash::merge
(Hash::merge!
) ici .