Hashes of Hashes Idiom in Ruby?

流过昼夜 提交于 2019-11-28 16:32:03

You can pass the Hash.new function a block that is executed to yield a default value in case the queried value doesn't exist yet:

h = Hash.new { |h, k| h[k] = Hash.new }

Of course, this can be done recursively.

/EDIT: Wow, there's an article answering this very question.

For the sake of completeness, here's the solution from the article for arbitrary depth hashes:

hash = Hash.new(&(p=lambda{|h,k| h[k] = Hash.new(&p)}))

Credits go to Kent from Data Noise.

Autovivification, as it's called, is both a blessing and a curse. The trouble can be that if you "look" at a value before it's defined, you're stuck with this empty hash in the slot and you would need to prune it off later.

If you don't mind a bit of anarchy, you can always just jam in or-equals style declarations which will allow you to construct the expected structure as you query it:

((h ||= { })['w'] ||= { })['z']
require 'xkeys'
h = {}.extend XKeys::Hash

h['x', 'y'] = value_to_insert
looked_up_value = h['w', 'z'] # nil

h[:foo, :bar, :baz, :else => 0] += 1
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!