into - ¿Cómo obtener una salida específica iterando un hash en Ruby?
ruby array (6)
Al llamar ordenar en un hash lo convierte en matrices anidadas y luego las ordena por clave, así que todo lo que necesita es esto:
puts h.sort.map {|k,v| ["#{k}----"] + v}
Y si realmente no necesita la parte "----", puede ser simplemente:
puts h.sort
Quiero obtener una salida específica iterando un Ruby Hash.
Este es el hash que quiero repetir:
hash = {
1 => [''a'', ''b''],
2 => [''c''],
3 => [''d'', ''e'', ''f'', ''g''],
4 => [''h'']
}
Esta es la salida que me gustaría obtener:
1-----
a
b
2-----
c
3-----
d
e
f
g
4-----
h
En Ruby, ¿cómo puedo obtener esa salida con mi Hash?
La forma más básica de iterar sobre un hash es la siguiente:
hash.each do |key, value|
puts key
puts value
end
Mi solución de una línea:
hash.each { |key, array| puts "#{key}-----", array }
Creo que es bastante fácil de leer.
También puede refinar Hash::each
para que admita la enumeración recursiva . Aquí está mi versión de Hash::each
( Hash::each_pair
) con soporte de bloque y enumerador :
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
Aquí hay ejemplos de uso de Hash::each
con y sin recursive
:
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
Aquí hay un ejemplo de la pregunta en sí:
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"]
También eche un vistazo a mi versión recursiva de Hash::merge
( Hash::merge!
) here .
hash.each do |key, array|
puts "#{key}-----"
puts array
end
Con respecto al orden, debo agregar que en 1.8 los elementos se iterarán en orden aleatorio (bueno, en realidad en un orden definido por la función hashing de Fixnum), mientras que en 1.9 se iterará en el orden del literal.
hash.keys.sort.each do |key|
puts "#{key}-----"
hash[key].each { |val| puts val }
end