Почему Hash.new({}) скрывает элементы хеша?[дубликат]

StackOverflow https://stackoverflow.com/questions/1822021

  •  10-07-2019
  •  | 
  •  

Вопрос

Итак, я хотел создать хеш, который имеет пустой хэш в качестве значения по умолчанию.Я знаю, это немного странно, но, скажем так, я подумал, что это может быть полезно.

Итак, вот что я сделал:

>> a = Hash.new({})
=> {}
>> a[:a][:b] = 5
=> 5
>> a
=> {}
>> a[:a]
=> {:b=>5}
>> a.keys
=> []
>> a.size
=> 0
>> a[:a].size
=> 1

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

Это ожидаемое поведение?Что здесь происходит?

Кстати, это Ruby 1.9.1, более ранние версии не пробовал.

Редактировать:упрощенный пример, поскольку это не обязательно должен быть хэш хэшей хэшей...

Это было полезно?

Решение

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

>> a[:a][:b] = 1
=> 1
>> a[:c][:d] = 2
=> 2
>> a[:d]
=> {:b=>1, :d=>2}

Принцип работы Hash.new с аргументом по умолчанию:Если ты это сделаешь hash[key] он проверяет, существует ли этот ключ в хеше.Если это так, он возвращает значение для этого ключа.Если нет, возвращается значение по умолчанию.Он не добавляет ключ в хэш и каждый раз возвращает один и тот же объект по умолчанию (а не копию).

Чтобы получить то, что вы хотите, вам нужно вместо этого указать блок по умолчанию.Таким образом, блок будет выполняться каждый раз, когда вы получаете доступ к ключу, которого нет в хеше.Внутри блока вы можете создать новый хэш и установить ключ так, чтобы он «указывал» на этот хэш.Вот так:

Hash.new { |h,k|  h[k] = {} }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top