Ruby 中转换树数据的算法

Algorithm to transform tree data in Ruby

如何将由哈希数组构成的树更改为另一种结构,例如:

我的数据如下:

{
  "A": [
         { "A1": [] },
         { "A2": [] },
         {
           "A3": [
                   {
                     "A31": [
                              { "A311": [] },
                              { "A312": [] }
                            ]
                   }
                 ]
         }
       ]
}

变成类似 :

{
  "name":     "A",
  "children": [
                { "name": "A1" },
                { "name": "A2" },
                {
                  "name":     "A3",
                  "children": [
                                {
                                  "name":     "A31",
                                  "children": [
                                                { "name": "A311" },
                                                { "name": "A312" }
                                              ]
                                }
                              ]
                }
              ]
}

我尝试了一些方法,但没有达到我希望的效果。

这就是我搬进我的树的方式

def recursive(data)
    return if data.is_a?(String)
    data.each do |d|
        keys = d.keys
        keys.each do |k|
            recursive(d[k])
        end
    end
   return data
end

我尽力跟随how to ask所以澄清:

λ = ->(h) { [h[:name], h[:children] ? h[:children].map(&λ).to_h : []] }

[λ.(inp)].to_h
#⇒ {
#  "A" => {
#    "A1" => [],
#    "A2" => [],
#    "A3" => {
#      "A31" => {
#        "A311" => [],
#        "A312" => []
#      }
#    }
#  }
# }

这个解决方案returns散列没有包裹在数组里面。如果你真的想用数组包装嵌套哈希,将它们映射到 λ.

当你不知道如何实现某件事时,总是先考虑最简单的情况。

第 1 步:将 {"A1" => []} 转换为 {"name" => "A1", "children" => []}

这很简单

def convert(hash)
  pair = hash.each_pair.first
  ["name", "children"].zip(pair).to_h
end

Step2:递归转换children

中的所有哈希值
def convert(hash)
  pair = hash.each_pair.first
  pair[1] = pair[1].map{|child| convert(child)}
  ["name", "children"].zip(pair).to_h
end

第 3 步:处理特殊情况

如果 children 为空则省略它。

def convert(hash)
  pair = hash.each_pair.first
  pair[1] = pair[1].map{|child| convert(child)}
  result = {"name" => pair[0]}
  result.merge!("children" => pair[1]) if pair[1].any?
  result
end