Matriz a Hash Ruby
Bien, así que este es el trato, he estado buscando en Google durante siglos para encontrar una solución a esto y, si bien hay muchos por ahí, no parecen hacer 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 un Hash para que se vea así
{ "item 1" => "item 2", "item 3" => "item 4" }
Es decir, los elementos que están en los índices 'par' son las claves y los elementos en los índices 'impar' son los valores.
¿Alguna idea de cómo hacer esto limpiamente? Supongo que un bruto el método de fuerza sería simplemente extraer todos los índices pares en una matriz separada y luego hacer un bucle alrededor de ellos para agregar los valores.
8 answers
Uso 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 está la respuesta para las versiones de ruby
a = ["item 1", "item 2", "item 3", "item 4"]
h = Hash[*a] # => { "item 1" => "item 2", "item 3" => "item 4" }
Eso es todo. El *
se llama el operador splat.
Una advertencia por @Mike Lewis (en los comentarios): "Ten mucho cuidado con esto. Ruby expande splats en la pila. Si hace esto con un conjunto de datos grande, espere eliminar su pila."
Por lo tanto, para la mayoría de los casos de uso general, este método es excelente, pero use un método diferente si desea hacerlo la conversión en una gran cantidad de 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]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-03 03:56:01
Ruby 2.1.0 introdujo un método to_h
en la matriz 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}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-13 21:40:06
Simplemente use Hash.[]
con los valores de la matriz. Por ejemplo:
arr = [1,2,3,4]
Hash[*arr] #=> gives {1 => 2, 3 => 4}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-01 20:38:27
O si tienes una matriz de [key, value]
matrices, puedes hacer:
[[1, 2], [3, 4]].inject({}) do |r, s|
r.merge!({s[0] => s[1]})
end # => { 1 => 2, 3 => 4 }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-11 06:42:01
Esto es lo que estaba buscando al googlear esto:
[{a: 1}, {b: 2}].reduce({}) { |h, v| h.merge v }
=> {:a=>1, :b=>2}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-16 06:47:44
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"}
Porque #each_slice
sin bloque nos da Enumerator
, y según la explicación anterior, podemos llamar al método #to_h
en el objeto Enumerator
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-27 12:34:55
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 perezoso 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"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-01 20:29:43
Usted podría intentar 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 array de array
irb(main):022:0> a = [[1, 2], [3, 4]]
=> [[1, 2], [3, 4]]
irb(main):023:0> Hash[*a.flatten]
=> {1=>2, 3=>4}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-06 09:52:18