De acuerdo, así que aquí está el trato, he estado buscando en Google durante años para encontrar una solución a esto y, aunque 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 '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 extraer todos los índices pares en una matriz separada y luego recorrerlos para agregar los valores.

*se llama el operador splat . Toma una matriz y la convierte en una lista literal de elementos. Entonces*[1,2,3,4]=>1, 2, 3, 4. En este ejemplo, lo anterior es equivalente a hacerHash["item 1", "item 2", "item 3", "item 4"]. YHashtiene un[]método que acepta una lista de argumentos (haciendo claves de índices pares y valores de índices impares), peroHash[]no acepta una matriz, por lo que la utilizamos*.Hash[a.each_slice(2).to_a].Ruby 2.1.0 introdujo un
to_hmétodo en Array que hace lo que usted requiere 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 .fuente
bardebe ser un símbolo, y el símbolo:2debe ser un número entero. Entonces, tu expresión corregida esa = [[:foo, 1], [:bar, 2]]).Solo use
Hash.[]con los valores en la matriz. Por ejemplo:fuente
*arrconviertearren una lista de argumentos, por lo que se llama al[]método de Hash con el contenido de arr como argumentos.O si tiene una matriz de
[key, value]matrices, puede hacer:fuente
Hash[*arr]{ [1, 2] => [3, 4] }. Y dado que el título de la pregunta dice "Array to Hash" y el método incorporado "Hash to Array" lo hace:{ 1 => 2, 3 => 4}.to_a # => [[1, 2], [3, 4]]pensé que más de uno podría terminar aquí tratando de obtener la inversa del método incorporado "Hash to Array". En realidad, así es como terminé aquí de todos modos.Hash[arr]hará el trabajo por ti.#injectmétodo. Con#merge!,#each_with_objectdebería haber sido utilizado. Si#injectse insiste en él, en#mergelugar de#merge!haberlo usado.Esto es lo que estaba buscando cuando busqué en Google:
[{a: 1}, {b: 2}].reduce({}) { |h, v| h.merge v } => {:a=>1, :b=>2}fuente
merge, construye y descarta una nueva iteración de hash por ciclo y es muy lenta. Si tiene una variedad de hash, intente en su[{a:1},{b:2}].reduce({}, :merge!)lugar: combina todo en el mismo hash (nuevo)..reduce(&:merge!)[{a: 1}, {b: 2}].reduce(&:merge!)evalúa a{:a=>1, :b=>2}[{a: 1}, {b: 2}].reduce(&:merge!)es lo mismo[{a: 1}, {b: 2}].reduce { |m, x| m.merge(x) }que lo mismo[{b: 2}].reduce({a: 1}) { |m, x| m.merge(x) }.EnumeratorincluyeEnumerable. Desde entonces2.1,Enumerabletambién tiene un método#to_h. Por eso, podemos escribir:Porque
#each_slicesin bloque nos daEnumerator, y según la explicación anterior, podemos llamar al#to_hmétodo en elEnumeratorobjeto.fuente
Podrías intentarlo así, para una sola matriz
para la matriz de la matriz
fuente
o, si odias
Hash[ ... ]:o, si eres un fanático perezoso de la programación funcional rota:
fuente
Hash[ ... ]pero quieres usarlo como un método encadenado (como puedes hacerloto_h), puedes combinar las sugerencias de Boris y escribir:arr.each_slice( 2 ).map { |e| e }.tap { |a| break Hash[a] }Todas las respuestas suponen que la matriz inicial es única. OP no especificó cómo manejar matrices con entradas duplicadas, lo que resulta en claves duplicadas.
Miremos a:
Perderá el
item 1 => item 2par ya que se anula bijitem 1 => item 5:Todos los métodos, incluido el
reduce(&:merge!)resultado en la misma eliminación.Sin embargo, podría ser que esto es exactamente lo que esperas. Pero en otros casos, es probable que desee obtener un resultado con un
Arrayvalor for:La forma ingenua sería crear una variable auxiliar, un hash que tenga un valor predeterminado y luego completarlo en un bucle:
Puede ser posible usar
assocyreducehacer lo anterior en una línea, pero eso se vuelve mucho más difícil de razonar y leer.fuente