Is there any way simpler than
if hash.key?('a')
hash['a']['b'] = 'c'
else
hash['a'] = {}
hash['a']['b'] = 'c'
end
Is there any way simpler than
if hash.key?('a')
hash['a']['b'] = 'c'
else
hash['a'] = {}
hash['a']['b'] = 'c'
end
If you create
hash
as the following, with default value of a new (identically default-valued) hash: (thanks to Phrogz for the correction; I had the syntax wrong)Then you can do
without any additional code.
The question here: Is auto-initialization of multi-dimensional hash array possible in Ruby, as it is in PHP? provides a very useful
AutoHash
implementation that does this.a simple one, but hash should be a valid hash object
Once you defined that, everything will work automatically. But be aware that from now on
nil
would behave as an empty hash when used as a hash.The easiest way is to construct your Hash with a block argument:
This form for
new
creates a new empty Hash as the default value. You don't want this:as that will use the exact same hash for all default entries.
Also, as Phrogz notes, you can make the auto-vivified hashes auto-vivify using
default_proc
:UPDATE: I think I should clarify my warning against
Hash.new({ })
. When you say this:That's pretty much like saying this:
And then, when you access
h
to assign something ash[:k][:m] = y
, it behaves as though you did this:And then, if you
h[:k2][:n] = z
, you'll end up assigningh.default[:n] = z
. Note thath
still says thath.has_key?(:k)
is false.However, when you say this:
Everything will work out okay because you will never modified
h[k]
in place here, you'll only read a value fromh
(which will use the default if necessary) or assign a new value toh
.