Ruby

 

Multi-value hashes in Ruby

 

Any non-trivial project quickly finds itself needing data structures that are more exotic than simple arrays or maps. In my quest for multimap nirvana, I first found references where every value-put call would need to be changed to look like this:

 

> h = {}
> (h[:key] ||= []) << "value 1"
> (h[:key] ||= []) << "value 2"
> puts h 
{:key=>["value 1", "value 2"]}

Obviously, not DRY, and painful to look at. I came across this post which talks about using the hash constructor:

> h = Hash.new{|h,k| h[k] = []}
> h[:key] << "value 1"
> h[:key] << "value 2"
> puts h
{:key=>["value 1", "value 2"]}

OK, I think I can live with that.

If you want a multi-value hash whose values are never duplicated, use Set.new in the constructor instead of an array.

If you need arbitrary-depth hashes, though, check this out:

> h = Hash.new{|h,k| h[k]=Hash.new(&h.default_proc) } 
> h[:a][:b][:c] = "123"
> puts h
{:a=>{:b=>{:c=>"123"}}}

The default_proc mechanics are explained very well here.

  1. Leave a comment

Leave a comment