Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting ruby hash .default to a list [duplicate]

Tags:

hashmap

ruby

I thought I understood what the default method does to a hash...

Give a default value for a key if it doesn't exist:

irb(main):001:0> a = {} => {} irb(main):002:0> a.default = 4 => 4 irb(main):003:0> a[8] => 4 irb(main):004:0> a[9] += 1 => 5 irb(main):005:0> a => {9=>5} 

All good.

But if I set the default to be a empty list, or empty hash, I don't understand it's behaviour at all....

irb(main):001:0> a = {} => {} irb(main):002:0> a.default = [] => [] irb(main):003:0> a[8] << 9 => [9]                          # great! irb(main):004:0> a => {}                           # ?! would have expected {8=>[9]} irb(main):005:0> a[8] => [9]                          # awesome! irb(main):006:0> a[9] => [9]                          # unawesome! shouldn't this be [] ?? 

I was hoping/expecting the same behaviour as if I had used the ||= operator...

irb(main):001:0> a = {} => {} irb(main):002:0> a[8] ||= [] => [] irb(main):003:0> a[8] << 9 => [9] irb(main):004:0> a => {8=>[9]} irb(main):005:0> a[9] => nil 

Can anyone explain what is going on?

like image 391
mat kelcey Avatar asked Oct 10 '08 10:10

mat kelcey


People also ask

How do I change a Hash value in Ruby?

The contents of a certain hash can be replaced in Ruby by using the replace() method. It replaces the entire contents of a hash with the contents of another hash.

How do you make Hash Hash in Ruby?

Ruby hash creation. A hash can be created in two basic ways: with the new keyword or with the hash literal. The first script creates a hash and adds two key-value pairs into the hash object. A hash object is created.


2 Answers

This is a very useful idiom:

(myhash[key] ||= []) << value 

It can even be nested:

((myhash[key1] ||= {})[key2] ||= []) << value 

The other way is to do:

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

But this has the significant side-effect that asking about a key will create it, which renders has_key? fairly useless, so I avoid this method.

like image 166
glenn mcdonald Avatar answered Sep 21 '22 12:09

glenn mcdonald


Hash.default is used to set the default value returned when you query a key that doesn't exist. An entry in the collection is not created for you, just because queried it.

Also, the value you set default to is an instance of an object (an Array in your case), so when this is returned, it can be manipulated.

a = {} a.default = []     # set default to a new empty Array a[8] << 9          # a[8] doesn't exist, so the Array instance is returned, and 9 appended to it a.default          # => [9] a[9]               # a[9] doesn't exist, so default is returned 
like image 32
Aaron Hinni Avatar answered Sep 24 '22 12:09

Aaron Hinni