Hash default value is a hash with same default val

2019-02-24 18:52发布

Setting a default value of a hash like this:

hash = Hash.new { |hsh, key| hsh[key] = {} }

will create (and assign) a new hash for an unknown key, but will return nil for an unknown key of the created hash:

hash[:unkown_key] #=> {}
hash[:unkown_key][:nested_unknown] #=> nil

I could make it work for the second level like this:

hash = Hash.new do |hsh, key|
  hsh[key] = Hash.new { |nest_hsh, nest_key| nest_hsh[nest_key] = {} }
end

but, it does not work at the third level:

hash[:unkown_key][:nested_unknown] #=> {}
hash[:unkown_key][:nested_unknown][:third_level] #=> nil

How can I make it work at arbitrary levels?

hash[:unkown_key][:nested_unknown][:third_level][...][:nth_level] #=> {}

3条回答
Evening l夕情丶
2楼-- · 2019-02-24 19:33

You could create method that will do this with Recursion

class Hash
  def self.recursive
    new { |hash, key| hash[key] = recursive }
  end
end

hash = Hash.recursive
hash[:unknown_key] # => {}
hash[:first_unknown_key][:second_unknown_key][...][:infinity]
# hash => {first_unknown_key:  {second_unknown_key: {... {infinity: {}}}}}
查看更多
何必那么认真
3楼-- · 2019-02-24 19:46

Sort of mind bending, but you can pass the hash's default_proc to the inner hash:

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

hash[:foo] #=> {}
hash[:foo][:bar] #=> {}
hash[:foo][:bar][:baz] #=> {}

hash #=> {:foo=>{:bar=>{:baz=>{}}}}
查看更多
做个烂人
4楼-- · 2019-02-24 19:46
bottomless_hash = ->() do
  Hash.new { |h, k| h[k] = bottomless_hash.call }
end

hash = bottomless_hash.call
hash[:unkown_key][:nested_unknown][:third_level][:fourth] # => {}
查看更多
登录 后发表回答