el siguiente código devuelve este error:
bloque en find_word_lengths': método no definido `[]=' para 3:Integer (NoMethodError)
animals = ['cat', 'horse', 'rabbit', 'deer'] def find_word_lengths(word_list) word_list.reduce(Hash.new()) do |result, animal| result[animal] = animal.length end end puts find_word_lengths(animals)El valor de retorno del bloque es el valor acumulado para la siguiente iteración. Así es como funciona un pliegue .
Las asignaciones en Ruby se evalúan en el lado derecho. Entonces, en la primera iteración de reduce , el bloque se evalúa como 3 (la longitud de 'cat' ). Lo que significa que en la segunda iteración de reduce , el result es 3 , y básicamente estás ejecutando
3['horse'] = 5 # which is equivalent to 3.[]=('horse', 5) Es por eso que recibe el mensaje de error de que Integer 3 no responde al mensaje []= .
Por lo tanto, debe asegurarse de que su bloque siempre devuelva el valor que desea usar para el acumulador en la próxima iteración. Algo como esto:
word_list.reduce(Hash.new()) do |result, animal| result.tap {|result| result[animal] = animal.length } endEsta sería la solución obvia, aunque algo engañosa.
word_list.reduce(Hash.new()) do |result, animal| result.merge(animal => animal.length) endSería más idiomático.
Sin embargo, cuando desea plegarse en un objeto mutable, tiene más sentido usar Enumerable#each_with_object en lugar deEnumerable#reduce . each_with_object ignora el resultado del bloque y simplemente pasa el mismo objeto cada vez. Tenga en cuenta que, de manera un tanto confusa, el orden de los parámetros del bloque se intercambia en each_with_object en comparación con reduce .
word_list.each_with_object(Hash.new()) do |animal, result| result[animal] = animal.length endPero supongo que la solución más idiomática sería algo como esto:
word_list.map {|word| [word, word.length] }.to_h Por cierto, en Ruby, es idiomático omitir los paréntesis para la lista de argumentos si no está pasando ningún argumento, por lo que Hash.new() debería ser Hash.new en su lugar. Aún más importante que ser idiomático es ser coherente: de manera confusa, omite los paréntesis para animal.length , pero no para Hash.new
Aún más idiomáticamente, usaría la notación literal Hash en lugar del método Hash::new , es decir, debería usar {} en lugar de Hash.new .