Hash of hashes

Hi all.

How can I create $Subject for future population?

···


Yours truly, WBR, Paul Argentoff.
Jabber: paul@jabber.rtelekom.ru
RIPE: PA1291-RIPE

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?

···

On Friday 03 October 2003 14:04, Paul Argentoff wrote:

How can I create $Subject for future population?


Yours truly, WBR, Paul Argentoff.
Jabber: paul@jabber.rtelekom.ru
RIPE: PA1291-RIPE

Paul Argentoff wrote:

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?

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>

···

On Friday 03 October 2003 14:04, Paul Argentoff wrote:

Dave Brown wrote:

In article 200310031434.31907.argentoff@rtelekom.ru,
: On Friday 03 October 2003 14:04, Paul Argentoff wrote:
:
: > 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…

···

Paul Argentoff argentoff@rtelekom.ru 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

···

On Friday 03 October 2003 14:48, Emmanuel Touzery wrote:

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>


Yours truly, WBR, Paul Argentoff.
Jabber: paul@jabber.rtelekom.ru
RIPE: PA1291-RIPE

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 :frowning:

···

On Friday 03 October 2003 14:48, Emmanuel Touzery wrote:

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>


Yours truly, WBR, Paul Argentoff.
Jabber: paul@jabber.rtelekom.ru
RIPE: PA1291-RIPE

“Joel VanderWerf” vjoel@PATH.Berkeley.EDU schrieb im Newsbeitrag
news:3F7E3AF2.2050701@path.berkeley.edu…

Dave Brown wrote:

In article 200310031434.31907.argentoff@rtelekom.ru,
: On Friday 03 October 2003 14:04, Paul Argentoff wrote:
:
: > 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
···

Paul Argentoff argentoff@rtelekom.ru wrote:

Paul Argentoff wrote:

···

On Friday 03 October 2003 14:48, Emmanuel Touzery wrote:

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%

This won’t work because you’re not doing what you’re expecting. What
you’re saying is that a nil key will return a particular Hash where
nil keys return a particular array.

This would be like saying:

arry = Array.new(2, 0)
hash = Hash.new(arry)
a = Hash.new(hash)

a[‘foo’] # => hash
a[‘foo’][‘bar’] # => arry

What you want is:

a = Hash.new do |h, k|
h[k] = Hash.new do |h1, k1|
h1[k1] = Array.new(2, 0)
end
end

This only works with 1.8 or bettter. Ruby does not auto-vivify
hashes or arrays like Perl. Note further that if you do something
like:

a = Hash.new { |h, k| h[k] = :val; nil }

You will get a perhaps surprising – but entirely correct – result:

a[‘foo’] # => nil
a[‘foo’] # => :val

When you attempt to access a nonexistant hash key, the default value
is returned. In this case, it’s nil. However, in the block you have
also set a side effect of setting the hash key provided to :val, so
the next time you access ‘foo’, it’s no longer nonexistant.

-austin

···

On Fri, 3 Oct 2003 20:17:50 +0900, Paul Argentoff wrote:

On Friday 03 October 2003 14:48, Emmanuel Touzery wrote:

not sure i understand your question. does this help you?
Here is my example:
irb(main):008:0> a = Hash.new(Hash.new(Array.new(2,0)))


austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2003.10.03
* 09.15.49

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}}}}}

“Paul Argentoff” argentoff@rtelekom.ru schrieb im Newsbeitrag
news:200310031517.45708.argentoff@rtelekom.ru

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 :frowning:

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
···

On Friday 03 October 2003 14:48, Emmanuel Touzery wrote:

Robert Klemme wrote:

“Joel VanderWerf” vjoel@PATH.Berkeley.EDU schrieb im Newsbeitrag

It would help to do

a = Hash.new {{}}

since you get a new hash each time…

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.

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

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

···

On Friday 03 October 2003 18:37, Joel VanderWerf wrote:

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


Yours truly, WBR, Paul Argentoff.
Jabber: paul@jabber.rtelekom.ru
RIPE: PA1291-RIPE

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

martin

···

Joel VanderWerf vjoel@path.berkeley.edu wrote:

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}}}}}

“Joel VanderWerf” vjoel@PATH.Berkeley.EDU schrieb im Newsbeitrag
news:3F7F0FF8.1030708@path.berkeley.edu…

Robert Klemme wrote:

“Joel VanderWerf” vjoel@PATH.Berkeley.EDU schrieb im Newsbeitrag

It would help to do

a = Hash.new {{}}

since you get a new hash each time…

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.

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

robert

Paul Argentoff wrote:

···

On Friday 03 October 2003 18:37, Joel VanderWerf wrote:

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 :-/

It might work with the shim module, from RAA.