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

Как назначить hash ['a'] ['b'] = 'c', если hash ['a'] не существует?

Есть ли какой-нибудь способ проще, чем

if hash.key?('a')
  hash['a']['b'] = 'c' 
else  
  hash['a'] = {}
  hash['a']['b'] = 'c' 
end
4b9b3361

Ответ 1

Самый простой способ - построить ваш хэш с помощью блока:

hash = Hash.new { |h, k| h[k] = { } }
hash['a']['b'] = 1
hash['a']['c'] = 1
hash['b']['c'] = 1
puts hash.inspect
# "{"a"=>{"b"=>1, "c"=>1}, "b"=>{"c"=>1}}"

Эта форма для new создает новый пустой Hash в качестве значения по умолчанию. Вы не хотите этого:

hash = Hash.new({ })

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

Кроме того, как отмечает Фрогз, вы можете сделать auto-vivived хэши самовоспроизводятся с помощью default_proc:

hash = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }

ОБНОВЛЕНИЕ. Я думаю, я должен уточнить свое предупреждение против Hash.new({ }). Когда вы это скажете:

h = Hash.new({ })

Это очень похоже на это:

h = Hash.new
h.default = { }

И затем, когда вы получаете доступ к h, чтобы назначить что-то как h[:k][:m] = y, он ведет себя так, как если бы вы это сделали:

if(h.has_key?(:k))
    h[:k][:m] = y
else
    h.default[:m] = y
end

И затем, если вы h[:k2][:n] = z, вы в конечном итоге назначаете h.default[:n] = z. Обратите внимание, что h все еще говорит, что h.has_key?(:k) является ложным.

Однако, когда вы говорите это:

h = Hash.new(0)

Все будет хорошо, потому что вы никогда не измените h[k] здесь, вы будете читать только значение из h (которое будет использовать по умолчанию, если необходимо) или назначить новое значение h.

Ответ 2

простой, но hash должен быть допустимым хеш-объектом

(hash["a"] ||= {})['b'] = "c"

Ответ 3

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

hash = Hash.new{ |h,k| h[k] = Hash.new(&h.default_proc) }

Затем вы можете сделать

hash["a"]["b"] = "c"

без дополнительного кода.

Ответ 5

class NilClass
  def [](other)
    nil
  end
end

Как только вы определили это, все будет работать автоматически. Но имейте в виду, что теперь nil будет вести себя как пустой хеш при использовании в качестве хеша.