hash default value

E

Emmanuel Touzery

Hello,

I'm bitten by a hash default value problem. I wanted to avoid the
myHash[a] = {} if !myHash[a]; myHash[a]["blue"] = 1
pattern by using hash default values, but i get an unexpected (for
me) result:

irb(main):001:0> myHash = {}
{}
irb(main):002:0> myHash["blue"]["red"] = 1
NameError: undefined method `[]=' for nil
from (irb):2
irb(main):003:0> myOtherHash = Hash.new({})
{}
irb(main):004:0> myOtherHash["blue"]["red"] = 1
1
irb(main):005:0> p myOtherHash
{}
nil

i expected that myOtherHash would be {"blue"=>{"red"=>1}}

what am i missing here? is there a workaround to the ugly syntax i said
i want to avoid? (you have the right to say "store your data in a decent
manner")

emmanuel

PS: don't think it matters, but i'm running ruby 1.6.7 (2002-03-01)
[i586-mswin32]
 
T

ts

E> irb(main):003:0> myOtherHash = Hash.new({})

You must use the block form

svg% ruby -e 'has = Hash.new {|h,k| h[k]={}}; has["blue"]["red"] = 1; p has'
{"blue"=>{"red"=>1}}
svg%

E> PS: don't think it matters, but i'm running ruby 1.6.7 (2002-03-01)

it will not work with 1.6.7

Guy Decoux
 
M

Mike Stok

Hello,

I'm bitten by a hash default value problem. I wanted to avoid the
myHash[a] = {} if !myHash[a]; myHash[a]["blue"] = 1
pattern by using hash default values, but i get an unexpected (for
me) result:

irb(main):001:0> myHash = {}
{}
irb(main):002:0> myHash["blue"]["red"] = 1
NameError: undefined method `[]=' for nil
from (irb):2
irb(main):003:0> myOtherHash = Hash.new({})
{}
irb(main):004:0> myOtherHash["blue"]["red"] = 1
1
irb(main):005:0> p myOtherHash
{}
nil

i expected that myOtherHash would be {"blue"=>{"red"=>1}}

what am i missing here? is there a workaround to the ugly syntax i said
i want to avoid? (you have the right to say "store your data in a decent
manner")

In recent rubys (I tried on 1.8) you can say

myHash = Hash.new { |h, k| h[k] = Hash.new }

so that the newly created sub-hash is installed in the original hash.

This behaves as you want...
myHash['blue']['red'] = 1 => 1
myHash['blue']['green'] = 2 => 2
myHash['crimson']['king'] = 69 => 69
p myHash
{"crimson"=>{"king"=>69}, "blue"=>{"green"=>2, "red"=>1}}

Hope this helps,

Mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top