example - Matriz para Hash Ruby
hash.map ruby (8)
Esto es lo que estaba buscando al buscar en Google esto:
[{a: 1}, {b: 2}].reduce({}) { |h, v| h.merge v } => {:a=>1, :b=>2}
De acuerdo, este es el trato, estuve buscando en Google durante años para encontrar una solución a esto y, aunque hay muchos por ahí, parece que no hacen el trabajo que estoy buscando.
Básicamente tengo una matriz estructurada como esta
["item 1", "item 2", "item 3", "item 4"]
Quiero convertir esto en Hash para que se vea así
{ "item 1" => "item 2", "item 3" => "item 4" }
es decir, los elementos que están en los índices "pares" son las claves y los elementos en los índices "impares" son los valores.
¿Alguna idea de cómo hacer esto limpiamente? Supongo que un método de fuerza bruta sería simplemente sacar todos los índices pares en una matriz separada y luego recorrerlos para agregar los valores.
O si tiene una matriz de matrices [key, value]
, puede hacer:
[[1, 2], [3, 4]].inject({}) do |r, s|
r.merge!({s[0] => s[1]})
end # => { 1 => 2, 3 => 4 }
Podrías probar así, para una sola matriz
irb(main):019:0> a = ["item 1", "item 2", "item 3", "item 4"]
=> ["item 1", "item 2", "item 3", "item 4"]
irb(main):020:0> Hash[*a]
=> {"item 1"=>"item 2", "item 3"=>"item 4"}
para una matriz de matriz
irb(main):022:0> a = [[1, 2], [3, 4]]
=> [[1, 2], [3, 4]]
irb(main):023:0> Hash[*a.flatten]
=> {1=>2, 3=>4}
Ruby 2.1.0 introdujo un método to_h
en Array que hace lo que necesita si su matriz original consiste en matrices de pares clave-valor: http://www.ruby-doc.org/core-2.1.0/Array.html#method-i-to_h .
[[:foo, :bar], [1, 2]].to_h
# => {:foo => :bar, 1 => 2}
Simplemente use Hash.[]
Con los valores en la matriz. Por ejemplo:
arr = [1,2,3,4]
Hash[*arr] #=> gives {1 => 2, 3 => 4}
Use to_h
:
a = ["item 1", "item 2", "item 3", "item 4"]
h = a.to_h # => { "item 1" => "item 2", "item 3" => "item 4" }
Para la posteridad, a continuación se encuentra la respuesta para las versiones de ruby <2.1.0:
a = ["item 1", "item 2", "item 3", "item 4"]
h = Hash[*a] # => { "item 1" => "item 2", "item 3" => "item 4" }
Eso es. El *
se llama el operador splat .
Una advertencia por @Mike Lewis (en los comentarios): "Ten mucho cuidado con esto. Ruby expande los símbolos en la pila. Si haces esto con un gran conjunto de datos, espera explotar tu pila".
Entonces, para la mayoría de los casos de uso general, este método es excelente, pero use un método diferente si desea realizar la conversión en muchos datos. Por ejemplo, @ Łukasz Niemier (también en los comentarios) ofrece este método para grandes conjuntos de datos:
h = Hash[a.each_slice(2).to_a]
Enumerator
incluye Enumerable
. Desde 2.1
, Enumerable
también tiene un método #to_h
. Por eso, podemos escribir:
a = ["item 1", "item 2", "item 3", "item 4"]
a.each_slice(2).to_h
# => {"item 1"=>"item 2", "item 3"=>"item 4"}
Debido a que #each_slice
sin bloque nos da el Enumerator
, y según la explicación anterior, podemos llamar al método #to_h
en el objeto Enumerator
.
a = ["item 1", "item 2", "item 3", "item 4"]
Hash[ a.each_slice( 2 ).map { |e| e } ]
o, si odias Hash[ ... ]
:
a.each_slice( 2 ).each_with_object Hash.new do |(k, v), h| h[k] = v end
o, si eres un fanático de la programación funcional rota:
h = a.lazy.each_slice( 2 ).tap { |a|
break Hash.new { |h, k| h[k] = a.find { |e, _| e == k }[1] }
}
#=> {}
h["item 1"] #=> "item 2"
h["item 3"] #=> "item 4"