On Mon, 22 Jan 2007 10:46:00 +0900, Joel VanderWerf wrote:

> Robert MannI wrote:
>> Hello!
>> 
>> 
>> I am wondering if the mighty ruby crowd has a brilliant idea for a tricky
>> problem I am solving.
>> 
>> I need to store a path as a tree in a hash.
>> 
>> Given:
>> a/b/c
>> 
>> I want the Hash:
>> { 'a' => { 'b' => { 'c' => { } } } }
>> or written differently
>> hsh['a']['b']['c'] = {}
> 
> This is a fairly standard idiom:
> 
> pr = proc {|h,k| h[k] = Hash.new(&pr)}
> 
> h = Hash.new(&pr)
> 
> h['a']['b']['c'] = {}
> 
> p h   # ==> {"a"=>{"b"=>{"c"=>{}}}}
> 
> For more discussion, search for "autovivify hash" on the list...
>

Then the inject trick becomes

pr = lambda {|h,k| h[k] = Hash.new(&pr)}
z=Hash.new(&pr)
s = "a/b/c"
s.split("/").inject(z){|ha,co| ha[co]}
s = "a/b/d"
s.split("/").inject(z){|ha,co| ha[co]}
s = "a/d/e"
s.split("/").inject(z){|ha,co| ha[co]}
s = "c/a/t"
s.split("/").inject(z){|ha,co| ha[co]}
p z

For some reason you can't name the hash h, otherwise the parameter
assignment in the proc will override it. Why is that, and is there any way
to avoid it?

This is what you really wanted because you wanted a really easy way to
merge all of these paths together into one hash, whereas if you
constructed the hashes separately then merged them you'd be losing data.
Try the following to see what I mean.

h1={'a'=>{'b'=>{'c'=>{}}}}
h2={'a'=>{'b'=>{'d'=>{}}}}
h3={'a'=>{'c'=>{'e'=>{}}}}
h4={'c'=>{'a'=>{'t'=>{}}}}
p h1.merge(h2).merge(h3).merge(h4)

All of the a/b branches are overwritten when 'a'=>{'c'...} is merged over
it. (And the second 'a'=>{'b'...} hash overwrites the first completely).

--Ken Bloom

-- 
Ken Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu/~kbloom1/