Подтвердить что ты не робот

Как я могу инициализировать массив внутри хеша в Ruby

Я пытаюсь инициализировать хэш массивов, например

@my_hash = Hash.new(Array.new)

чтобы я мог:

@my_hash["hello"].push("in the street")
=> ["in the street"]
@my_hash["hello"].push("at home")
=> ["in the street", "at home"]
@my_hash["hello"]
=>["in the street", "at home"]

Проблема в том, что любой новый хеш-ключ также возвращает ["in the street", "at home"]

@my_hash["bye"]
=> ["in the street", "at home"]
@my_hash["xxx"]
=> ["in the street", "at home"]

!!!???

Что я делаю неправильно, что было бы правильным способом инициализировать хеш массивов?

4b9b3361

Ответ 1

@my_hash = Hash.new(Array.new)

Это создает ровно один объект массива, который возвращается каждый раз, когда ключ не найден. Поскольку вы только когда-либо мутируете этот массив и никогда не создаете новый, все ваши ключи сопоставляются с одним и тем же массивом.

Что вы хотите сделать:

@my_hash = Hash.new {|h,k| h[k] = Array.new }

или просто

@my_hash = Hash.new {|h,k| h[k] = [] }

Передача блока в Hash.new отличается от простого прохождения аргумента двумя способами:

  • Блок выполняется каждый раз, когда ключ не найден. Таким образом, вы будете получать новый массив каждый раз. В версии с аргументом этот аргумент оценивается один раз (до вызова new), и результат этого возвращается каждый раз.

  • Выполняя h[k] =, вы фактически вставляете ключ в хэш. Если вы этого не сделаете, доступ к @my_hash[some_key] не приведет к тому, что some_key будет вставлен в хэш.

Ответ 2

Попробуйте следующее:

@my_hash = Hash.new { |h, k| h[k] = Array.new }

Ответ 3

Аргумент для Hash.new для значения по умолчанию для новых хеш-ключей, поэтому, когда вы передаете ему ссылку, эта ссылка будет использоваться для новых хеш-ключей. Вы обновляете эту ссылку при вызове...

hash["key"].push "value"

Вам нужно передать новую ссылку в хэш-ключ, прежде чем нажимать на нее значения...

hash["key1"] = Array.new
hash["key1"].push "value1"
hash["key2"] = Array.new
hash["key2"].push "value2

Вы также можете попробовать инкапсулировать это в вспомогательный метод.