Ruby внедрить с начальным хешем - PullRequest
48 голосов
/ 24 февраля 2012

Может кто-нибудь сказать мне, почему следующее:

['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"

Ответы [ 3 ]

72 голосов
/ 24 февраля 2012

Ваш блок должен вернуть накопительный хеш:

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

Вместо этого он возвращает строку «a» после первого прохода, которая становится m на следующем проходе, и в итоге вы вызываете метод []= строки.

47 голосов
/ 24 февраля 2012

Блок должен вернуть аккумулятор (хеш), как сказал @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] }]

С Array#to_h (Ruby> = 2,1):

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

С Перечислимый # пюре из граней:

require 'facets'
hash = ['a', 'b'].mash { |e| [e, e] }
20 голосов
/ 24 февраля 2012

Вместо того, чтобы использовать инъекцию, вы должны изучить 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 обращают порядок полученных параметров.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...