Взаимодействие между хэш-значением и оператором << << ` - PullRequest
0 голосов
/ 04 декабря 2018

Я ожидал:

h = Hash.new([])
h['a'] << 'b'
h['a'] << 'c'
h # => {}

даст {'a' => ['b','c']}, а не пустой хеш.

Я также обнаружил, что операция вставки нацеливается на значение по умолчанию, поскольку после приведенного выше кода она равна ['b','c']:

h.default # => ['b','c']

Я ищу объяснение, почемуне работает и как это сделать оптимально, чтобы он работал.

Ответы [ 3 ]

0 голосов
/ 04 декабря 2018

Это потому, что h не имеет ключа 'a', вам нужно инициализировать его раньше, или это просто сброс значения по умолчанию:

h = Hash.new([])
h['a'] = ['b']
h['a'] << 'c'

h['a'] #=> ["b", "c"]
h #=> {"a"=>["b", "c"]}

Это ведет себя так же:

k = Hash.new
k.default = []

Хотя, как объяснил Серхио Туленцев, (https://stackoverflow.com/a/53614695/5239030) это создает ключ «на лету», попробуйте это:

k = Hash.new {|h, k| puts "Just created a new key: #{k}"; h[k] = [] }
p k['a'] << 'a'
p k['a'] << 'a'
p k['b'] << 'b'
p k
0 голосов
/ 04 декабря 2018

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

Чтобы сделать то, что вы хотите, используйте третью форму Hash.new

new {|hash, key| block } → new_hash

, например, например,

h = Hash.new {|h, k| h[k] = [] }
0 голосов
/ 04 декабря 2018

Это потому, что вы изменили этот конкретный объект, который вы передали в качестве значения по умолчанию.Итак:

h = Hash.new([])
h['a'] << 'b'
h['a'] << 'c'
h['b'] # or h['a'] or h[:virtually_anything]
# => ["b", "c"]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...