如何使用键数组动态添加嵌套哈希值?

时间:2013-03-22 01:36:25

标签: ruby-on-rails ruby

this SO answer开始,我可以动态创建嵌套的哈希值:

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

例如:

hash = Hash.new{ |h,k| h[k] = Hash.new(&h.default_proc) }
hash['a']['b']['c'] = { 'key' => 'value' }
#=> {'a' => { 'b' => { 'c' => { 'key' => 'value' }}}}

到目前为止一切顺利。

我需要这个:

hash = Hash.new{ |h,k| h[k] = Hash.new(&h.default_proc) }
hash['a', 'b', 'c'] = { 'key' => 'value' }
#=> {'a' => { 'b' => { 'c' => { 'key' => 'value' }}}}

我更喜欢它保留层次结构中存在的任何其他哈希值,并根据需要创建新的哈希值。

我对红宝石中的元编程相当新,我们非常感谢。

2 个答案:

答案 0 :(得分:3)

实现我想你想要的一种方法是给予相同的自动生成散列技术,而不必重新定义Hash#[]就是在给定所需数组的每个元素的情况下简单地遍历散列(更深入)。我能想到的最常用的方法是使用Array#inject

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

# array of keys
keys = ['a', 'b', 'c']

# "Injection", a.k.a, "go deeper" ;)
keys.inject(hash) {|h, k|
  h[k]
}['key'] = 'value'   # assign 'value' to 'key' on last/deepest hash

p hash               # {"a"=>{"b"=>{"c"=>{"key"=>"value"}}}}

hash['a', 'b', 'c']不完全相同(因为这是一个语法错误),但我收集它是你需要的。

答案 1 :(得分:1)

这是我得到的最接近的,却不知道“我更喜欢保留层次结构中存在的任何其他哈希值”的含义。由于某种原因,该方法的返回值并不完美,但我有点太累了,无法找出原因(欢迎任何评论)。

class MyH < Hash
  def []= (*keys, value)
    self.merge! keys.reverse.inject(value){|mem,obj| {obj => mem } }
    self
  end
end

hash = MyH.new
# => {}
hash['a', 'b', 'c'] = { 'key' => 'value' }
# => {"key"=>"value"}
hash
# => {"a"=>{"b"=>{"c"=>{"key"=>"value"}}}}