Ответ 1
Ваш блок должен вернуть накопленный хеш:
['a', 'b'].inject({}) {|m,e| m[e] = e; m }
Вместо этого он возвращает строку 'a' после первого прохода, который становится m
в следующем проходе, и вы вызываете метод string []=
.
Может ли кто-нибудь сказать мне, почему следующее:
['a', 'b'].inject({}) {|m,e| m[e] = e }
выдает ошибку:
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>'
тогда как работает?
a = {}
a["str"] = "str"
Ваш блок должен вернуть накопленный хеш:
['a', 'b'].inject({}) {|m,e| m[e] = e; m }
Вместо этого он возвращает строку 'a' после первого прохода, который становится m
в следующем проходе, и вы вызываете метод string []=
.
Блок должен вернуть аккумулятор (хэш), как сказал @Rob. Некоторые альтернативы:
С Hash#update
:
hash = ['a', 'b'].inject({}) { |m, e| m.update(e => e) }
С Enumerable#each_with_object
:
hash = ['a', 'b'].each_with_object({}) { |e, m| m[e] = e }
С Hash#[]
:
hash = Hash[['a', 'b'].map { |e| [e, e] }]
С Перечислить # mash из граней:
require 'facets'
hash = ['a', 'b'].mash { |e| [e, e] }
С Array#to_h
(Ruby >= 2.1):
hash = ['a', 'b'].map { |e| [e, e] }.to_h
Вместо использования инъекции вы должны изучить Enumerable#each_with_object
.
Где inject
требуется, чтобы вы вернули накопленный объект, each_with_object
делает это автоматически.
Из документов:
Итерирует заданный блок для каждого элемента с заданным произвольным объектом и возвращает первоначально заданный объект.
Если ни один блок не указан, возвращается перечислитель.
например:.
evens = (1..10).each_with_object([]) {|i, a| a << i*2 }
#=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
Итак, ближе к вашему вопросу:
[1] pry(main)> %w[a b].each_with_object({}) { |e,m| m[e] = e }
=> {"a"=>"a", "b"=>"b"}
Обратите внимание, что inject
и each_with_object
отменят порядок заданных параметров.