Есть ли какой-нибудь способ проще, чем
if hash.key?('a')
hash['a']['b'] = 'c'
else
hash['a'] = {}
hash['a']['b'] = 'c'
end
Есть ли какой-нибудь способ проще, чем
if hash.key?('a')
hash['a']['b'] = 'c'
else
hash['a'] = {}
hash['a']['b'] = 'c'
end
Самый простой способ - построить ваш хэш с помощью блока:
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
.
простой, но hash должен быть допустимым хеш-объектом
(hash["a"] ||= {})['b'] = "c"
Если вы создаете hash
следующим образом, со значением по умолчанию нового (тождественно по умолчанию) хэша: (спасибо Phrogz за исправление, у меня был синтаксис неправильный)
hash = Hash.new{ |h,k| h[k] = Hash.new(&h.default_proc) }
Затем вы можете сделать
hash["a"]["b"] = "c"
без дополнительного кода.
Вопрос здесь:
Возможна ли автоматическая инициализация многомерного хеш-массива в Ruby, как в PHP?
обеспечивает очень полезную реализацию AutoHash
, которая делает это.
class NilClass
def [](other)
nil
end
end
Как только вы определили это, все будет работать автоматически. Но имейте в виду, что теперь nil
будет вести себя как пустой хеш при использовании в качестве хеша.