On Mon, 22 Jan 2007, Ken Bloom wrote:

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

i think it's less overhead to simply name the top hash and return it

harp:~ > cat a.rb
p( 'a/b/c'.split('/').inject(r={}){|h,k| h[k] = h={}} && r )

harp:~ > ruby a.rb
{"a"=>{"b"=>{"c"=>{}}}}


>
> 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).
>

you are almost certainly right.  good point!

-a
-- 
we can deny everything, except that we have the possibility of being better.
simply reflect on that.
- the dalai lama