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.