如何使用ruby哈希以递归方式收集深层嵌套的键

时间:2014-12-16 03:10:36

标签: ruby

我正在寻找一种聪明的方法来收集深层嵌套键的父键并将它们指定为值。例如......

像哈希一样......

{
  :foo => {
    :bar => {
      :baz => 'a',
      :bez => 'b',
      :biz => 'c'
    }
  }
}

并像这样创建一个哈希...

{
  :foo => {
    :bar => {
      :baz => [:foo, :bar, :baz],
      :bez => [:foo, :bar, :bez],
      :biz => [:foo, :bar, :biz]
    }
  }
}

3 个答案:

答案 0 :(得分:2)

尝试递归解决方案:

# array of parent keys initially []
def nested(hash, keys = [])
  # go through each key-value pair
  hash.each do |key, val|
    # if the value is a Hash, recurse and
    # add the key to the array of parents
    if val.is_a? Hash
      nested(val, keys.push(key))
      # remove last parent when we're done
      # with this pair
      keys.pop
    else
      # if the value is not a Hash, set the
      # value to parents + current key
      hash[key] = keys + [key]
    end
  end
end

答案 1 :(得分:1)

制作递归函数。

def recurse(h, acc=[])
  Hash[h.map { |key, value|
    if value.is_a? Hash
      [key, recurse(value, acc + [key])]
    else
      [key, acc + [key]]
    end
  }]
  # You can use h.map {...}.to_h in Ruby 2.1+
end

recurse({
  :foo => {
    :bar => {
      :baz => 'a',
      :bez => 'b',
      :biz => 'c'
    }
  }
})
# =>  {:foo=>
#       {:bar=>
#         {:baz=>[:foo, :bar, :baz],
#                 :bez=>[:foo, :bar, :bez],
#                 :biz=>[:foo, :bar, :biz]}}}

答案 2 :(得分:1)

我建议进行以下递归。

<强>代码

def rehash(h, keys = [])
  h.each_with_object({}) { |(k,v),g|
    g[k] = case v
           when Hash then rehash(v, keys+[k]) 
           else           (keys + [k])       
           end
  }
end

示例

h = { :foo => {
        :bar => {
          :baz => 'a',
          :bez => 'b',
          :biz => 'c'
        }
      }
    }

rehash(h)  
  #=> {:foo=>
        {:bar=>
          {:baz=>[:foo, :bar, :baz],
           :bez=>[:foo, :bar, :bez],
           :biz=>[:foo, :bar, :biz]}}}