Я намагаюся ініціалізувати Hash масивів, таких як
@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 масивів?
Відповіді:
85 для відповіді № 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
для вставки в хеш.
7 для відповіді № 2
Спробуйте це:
@my_hash = Hash.new { |h, k| h[k] = Array.new }
2 для відповіді № 3
Аргументом для Hash.new є значення за замовчуванням для нових ключів хешу, тому, коли ви передаєте йому посилання, посилання буде використано для нових ключів хешу. Ви поновлюєте цю посилання, коли ви телефонуєте ...
hash["key"].push "value"
Потрібно передати нове посилання в хеш-ключ, перш ніж натискати на нього значення ...
hash["key1"] = Array.new
hash["key1"].push "value1"
hash["key2"] = Array.new
hash["key2"].push "value2
Можна також спробувати інкапсулювати це у допоміжний метод.