Skip to content

Instantly share code, notes, and snippets.

@granolocks
Created May 6, 2012 20:14
Show Gist options
  • Save granolocks/2624185 to your computer and use it in GitHub Desktop.
Save granolocks/2624185 to your computer and use it in GitHub Desktop.
Multi-value hashes in Ruby
# Multi-value hashes in Ruby
# Posted on March 24, 2011
# http://matthew.mceachen.us/blog/multi-value-hashes-in-ruby-1114.html
# 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: http://railsforum.com/viewtopic.php?pid=113682#p113682.
# Comment: "this is called autovivification ;)"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment