Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specifying default value for Hash of hashes in Ruby [duplicate]

Tags:

ruby

Lets say I have a Hash called person whose key is name and value is a hash having keys 'age' and 'hobby'. An entry in the hash person would look like

=> person["some_guy"] = {:hobby => "biking", :age => 30}

How would I go about specifying the default for the hash 'person'? I tried the following

=> person.default = {:hobby => "none", :age => 20}

but it doesn't work.

EDIT:

I was setting one attribute and expecting others to be auto-populated. For eg.

=> person["dude"][:age] += 5

and this is what I was seeing

=> person["dude"]
=> {:hobby => "none", :age => 25}

which is fine. However, typing person at the prompt, I get an empty hash.

=> person
=> {}

However, what I was expecting was

=> person
=> {"dude" => {:hobby => "none", :age => 25}}
like image 449
kshenoy Avatar asked Jan 17 '23 11:01

kshenoy


2 Answers

Why It May Not Work for You

You can't call Hash#default if an object doesn't have the method. You need to make sure that person.is_a? Hash before it will work. Are you sure you don't have an array instead?

It's also worth noting that a hash default doesn't populate anything; it's just the value that's returned when a key is missing. If you create a key, then you still need to populate the value.

Why It Works for Me

# Pass a default to the constructor method.
person = Hash.new({hobby: "", age: 0})
person[:foo]
=> {:hobby=>"", :age=>0}

# Assign a hash literal, and then call the #default method on it.
person = {}
person.default = {hobby: "", age: 0}
person[:foo]
=> {:hobby=>"", :age=>0}

What You Probably Want

Since hash defaults only apply to missing keys, not missing values, you need to take a different approach if you want to populate a hash of hashes. One approach is to pass a block to the hash constructor. For example:

person = Hash.new {|hash,key| hash[key]={hobby: nil, age:0}}
=> {}

person[:foo]
=> {:hobby=>nil, :age=>0}

person[:bar]
=> {:hobby=>nil, :age=>0}

person
=> {:foo=>{:hobby=>nil, :age=>0}, :bar=>{:hobby=>nil, :age=>0}}
like image 156
Todd A. Jacobs Avatar answered Jan 31 '23 09:01

Todd A. Jacobs


You can specify a hash's default value on instantiation by passing the default value to the .new method:

person = Hash.new({ :hobby => '', :age => 0 })
like image 22
Samy Dindane Avatar answered Jan 31 '23 09:01

Samy Dindane