Как я могу инициализировать массив внутри хэша в Ruby - PullRequest
34 голосов
/ 10 декабря 2010

Я пытаюсь инициализировать Hash of Arrays, например

@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"]

!!! ???

Что я делаю не так, каков был бы правильный способ инициализации Hash of Arrays?

Ответы [ 3 ]

90 голосов
/ 10 декабря 2010
@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 отличается от простой передачи аргумента двумя способами:

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

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

7 голосов
/ 10 декабря 2010

Попробуйте это:

@my_hash = Hash.new { |h, k| h[k] = Array.new }
2 голосов
/ 10 декабря 2010

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

hash["key"].push "value"

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

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

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

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