ruby

hash each ruby



Inyectar Ruby con ser inicial un hash (3)

¿Alguien puede decirme por qué lo siguiente?

[''a'', ''b''].inject({}) {|m,e| m[e] = e }

arroja el error:

IndexError: string not matched from (irb):11:in `[]='' from (irb):11:in `block in irb_binding'' from (irb):11:in `each'' from (irb):11:in `inject'' from (irb):11 from C:/Ruby192/bin/irb:12:in `<main>''

mientras que las siguientes obras?

a = {} a["str"] = "str"


El bloque debe devolver el acumulador (el hash), como dijo @Rob. Algunas alternativas:

Con la Hash#update :

hash = [''a'', ''b''].inject({}) { |m, e| m.update(e => e) }

Con Enumerable#each_with_object :

hash = [''a'', ''b''].each_with_object({}) { |e, m| m[e] = e }

Con Hash#[] :

hash = Hash[[''a'', ''b''].map { |e| [e, e] }]

Con Enumerable#mash de Facets:

require ''facets'' hash = [''a'', ''b''].mash { |e| [e, e] }

Con Array#to_h (Ruby> = 2.1):

hash = [''a'', ''b''].map { |e| [e, e] }.to_h


En lugar de usar la inyección, debe buscar en Enumerable#each_with_object .

Donde inject requiere devolver el objeto que se está acumulando, each_with_object hace automáticamente.

De los documentos:

Itera el bloque dado para cada elemento con un objeto arbitrario dado, y devuelve el objeto dado inicialmente.

Si no se proporciona ningún bloque, devuelve un enumerador.

p.ej:

evens = (1..10).each_with_object([]) {|i, a| a << i*2 } #=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Entonces, más cerca de tu pregunta:

[1] pry(main)> %w[a b].each_with_object({}) { |e,m| m[e] = e } => {"a"=>"a", "b"=>"b"}

Observe que inject y each_with_object invierten el orden de los parámetros cedidos.


Tu bloque necesita devolver el hash acumulativo:

[''a'', ''b''].inject({}) {|m,e| m[e] = e; m }

En cambio, está devolviendo la cadena ''a'' después del primer pase, que se convierte en m en el siguiente pase y terminas llamando al método []= la cadena.