BioDevMike BioDevMike - 1 month ago 5
Perl Question

One liner nested hash creation in Ruby? (I come from Perl)

I am a Perl person and I have made Hashes like this for a while:


my %date;

#Assume the scalars are called with 'my' earlier

$date{$month}{$day}{$hours}{$min}{$sec}++


Now I am learning Ruby and I have so far found that using this tree is the way to do many keys and a value. Is there any way to use the simple format that I use with Perl using one line?


@date = {
month => {
day => {
hours => {
min => {
sec => 1
}
}
}
}
}

Answer

Unfortunately, there is no simple, practical way. A Ruby equivalent would be an ugly, ugly beast like:

((((@date[month] ||= {})[day] ||= {})[hours] ||= {})[min] ||= {})[sec] = 1

There is a way to assign default values for missing keys in hashes, though:

@date = Hash.new { |hash, key| hash[key] = {} }

# @date[:month] is set to a new, empty hash because the key is missing.
@date[:month][:day] = 1

Unfortunately this does not work recursively.

...unless you create it yourself; hooray for Ruby!

class Hash
  def self.recursive
    new { |hash, key| hash[key] = recursive }
  end
end

@date = Hash.recursive
@date[month][day][hours][min][sec] = 1
# @date now equals {month=>{day=>{hours=>{min=>{sec=>1}}}}}

Keep in mind, though, that all unset values are now {} rather than nil.

Comments