hash of hashes

P

Paul Argentoff

How can I create $Subject for future population?

Let's put it this way: I need to create a nested hash which will be populated
later by referencing the keys in the subhashes. How can I do this?
 
E

Emmanuel Touzery

Paul said:
Let's put it this way: I need to create a nested hash which will be populated
later by referencing the keys in the subhashes. How can I do this?
not sure i understand your question. does this help you?

irb(main):001:0> a = {}
{}
irb(main):002:0> a["blue"] = {}
{}
irb(main):003:0> a["blue"]["red"] = 3
3
irb(main):004:0> a["blue"]
{"red"=>3}
irb(main):005:0> a["blue"]["red"]
3
irb(main):006:0>
 
P

Paul Argentoff

irb(main):001:0> a = {}
{}
irb(main):002:0> a["blue"] = {}
{}
irb(main):003:0> a["blue"]["red"] = 3
3
irb(main):004:0> a["blue"]
{"red"=>3}
irb(main):005:0> a["blue"]["red"]
3
irb(main):006:0>

I need something like this:

a = {{}} # this doesn't work, but i've just written it here to emph. the
# subject
...
# somewhere in the iteration
a[foo][bar] = baz
...
 
E

Emmanuel Touzery

Paul said:
irb(main):001:0> a = {}
{}
irb(main):002:0> a["blue"] = {}
{}
irb(main):003:0> a["blue"]["red"] = 3
3
irb(main):004:0> a["blue"]
{"red"=>3}
irb(main):005:0> a["blue"]["red"]
3
irb(main):006:0>

I need something like this:

a = {{}} # this doesn't work, but i've just written it here to emph. the
# subject
...
# somewhere in the iteration
a[foo][bar] = baz
...
i think you need ruby 1.8's block form for creating hashes. i asked that
question recently, and here is the snippet from Guy Decoux:

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

Paul Argentoff

not sure i understand your question. does this help you?

irb(main):001:0> a = {}
{}
irb(main):002:0> a["blue"] = {}
{}
irb(main):003:0> a["blue"]["red"] = 3
3
irb(main):004:0> a["blue"]
{"red"=>3}
irb(main):005:0> a["blue"]["red"]
3
irb(main):006:0>

Here is my example:

irb(main):008:0> a = Hash.new(Hash.new(Array.new(2,0)))
=> {}
irb(main):009:0> a['foo']['bar'][1] = 2
=> 2
irb(main):010:0> a['foo']['bar']
=> [0, 2]
irb(main):011:0> a.keys
=> []
irb(main):012:0>

After this I can't iterate over a's keys -- what I've written the whole mess
for :(
 
J

Joel VanderWerf

Paul Argentoff wrote:
...
I need something like this:

a = {{}} # this doesn't work, but i've just written it here to emph. the
# subject
...
# somewhere in the iteration
a[foo][bar] = baz
...

hash_maker = proc do |h, k|
h[k] = Hash.new(&hash_maker)
end

h = Hash.new(&hash_maker)

h[1][2][3][4][5] = 6

p h # {1=>{2=>{3=>{4=>{5=>6}}}}}
 
P

Paul Argentoff

hash_maker = proc do |h, k|
   h[k] = Hash.new(&hash_maker)
end

:))) Exmaple is worthy of a Haskell tutorial :)))

The problem is, afaik, that I tried to do THAT with Ruby 1.6 :-/
 
D

Dave Brown

:
: > How can I create $Subject for future population?
:
: Let's put it this way: I need to create a nested hash which will be populated
: later by referencing the keys in the subhashes. How can I do this?

You mean, er,

irb(main):001:0> a=Hash.new({})
=> {}
irb(main):002:0> a['foo']
=> {}

?

--Dave
 
J

Joel VanderWerf

Dave said:
:
: > How can I create $Subject for future population?
:
: Let's put it this way: I need to create a nested hash which will be populated
: later by referencing the keys in the subhashes. How can I do this?

You mean, er,

irb(main):001:0> a=Hash.new({})
=> {}
irb(main):002:0> a['foo']
=> {}

?

--Dave

That's like, a real bad trip, dude:

irb(main):002:0> a=Hash.new({})
=> {}
irb(main):003:0> a[1]
=> {}
irb(main):004:0> a[1]["x"] = "y"
=> "y"
irb(main):005:0> a
=> {}
irb(main):006:0> a[1]
=> {"x"=>"y"}
irb(main):007:0> a[1] = 2
=> 2
irb(main):008:0> a[2]
=> {"x"=>"y"}
irb(main):009:0> a[1]
=> 2

It would help to do

a = Hash.new {{}}

since you get a new hash each time...
 
M

Martin DeMello

Joel VanderWerf said:
hash_maker = proc do |h, k|
h[k] = Hash.new(&hash_maker)
end

h = Hash.new(&hash_maker)

h[1][2][3][4][5] = 6

p h # {1=>{2=>{3=>{4=>{5=>6}}}}}

My head hurts :) That needs to go on the Ruby Idioms page.

martin
 
R

Robert Klemme

Paul Argentoff said:
not sure i understand your question. does this help you?

irb(main):001:0> a = {}
{}
irb(main):002:0> a["blue"] = {}
{}
irb(main):003:0> a["blue"]["red"] = 3
3
irb(main):004:0> a["blue"]
{"red"=>3}
irb(main):005:0> a["blue"]["red"]
3
irb(main):006:0>

Here is my example:

irb(main):008:0> a = Hash.new(Hash.new(Array.new(2,0)))
=> {}
irb(main):009:0> a['foo']['bar'][1] = 2
=> 2
irb(main):010:0> a['foo']['bar']
=> [0, 2]
irb(main):011:0> a.keys
=> []
irb(main):012:0>

After this I can't iterate over a's keys -- what I've written the whole mess
for :(

That's because the form Hash.new( obj ) just replaces the nil return value
for keys that are not found. In your example you have a hash that returns a
hash for unknown keys that in turn returns an array for unknown keys. You
definitely need the block form. Or you have to wrap or sub class the hash
if you want to use pre 1.8 ruby versions.

Regards

robert
 
R

Robert Klemme

Joel VanderWerf said:
Dave said:
:
: > How can I create $Subject for future population?
:
: Let's put it this way: I need to create a nested hash which will be populated
: later by referencing the keys in the subhashes. How can I do this?

You mean, er,

irb(main):001:0> a=Hash.new({})
=> {}
irb(main):002:0> a['foo']
=> {}

?

--Dave

That's like, a real bad trip, dude:

irb(main):002:0> a=Hash.new({})
=> {}
irb(main):003:0> a[1]
=> {}
irb(main):004:0> a[1]["x"] = "y"
=> "y"
irb(main):005:0> a
=> {}
irb(main):006:0> a[1]
=> {"x"=>"y"}
irb(main):007:0> a[1] = 2
=> 2
irb(main):008:0> a[2]
=> {"x"=>"y"}
irb(main):009:0> a[1]
=> 2

It would help to do

a = Hash.new {{}}

since you get a new hash each time...

Not really:

irb(main):001:0> h=Hash.new{{}}
=> {}
irb(main):002:0> h[1][2]="foo"
=> "foo"
irb(main):003:0> h
=> {}
irb(main):004:0>

You need a = Hash.new {|h,k| h[k]={}} as pointed out already.

robert
 
J

Joel VanderWerf

Robert said:
Not really:

Oops. Of course you're right, since the value returned by the block is
never assigned to any part of the hash. You always have to do that yourself.
 
R

Robert Klemme

Joel VanderWerf said:
Oops. Of course you're right, since the value returned by the block is
never assigned to any part of the hash. You always have to do that
yourself.

.... and it's always the same. Something not wanted in this case.

robert
 

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

No members online now.

Forum statistics

Threads
474,137
Messages
2,570,795
Members
47,342
Latest member
eixataze

Latest Threads

Top