将目录数组转换为特定的嵌套哈希

时间:2017-06-12 19:55:45

标签: ruby-on-rails ruby

我有以下" dir路径"目录树结构的数组。数组的每个元素都是包含路径部分作为其元素的数组。这是一个按"层次结构"排序的样本。作为Ruby on Rails private方法的结果,每个元素还包含pluck布尔标志:

[
  [["Dir 01"], false],
  [["Dir 02"], true],
  [["Dir 01", "Dir 01 01"], false],
  [["Dir 01", "Dir 01 02"], false],
  [["Dir 01", "Dir 01 02", "Dir 01 02 01"], false]
]

我需要在Ruby中转换为以下数组哈希结构:

[
    {:title => "Dir 01",
        :private => false,
        :sub_dirs => [
            {:title => "Dir 01 01", :private => false},
            {:title => "Dir 01 02",
                :private => false,
                :sub_dirs => [
                    {:title => "Dir 01 02 01", :private => false}
                ]},
        ]},
    {:title => "Dir 02", :private => true}
]

到目前为止,我已经尝试过这段代码:

arr = Array.new
dirs.each { |dir| arr << dir[0].reverse.inject({private: dir[1]}) { |a, n| { n => a } } }

生成以下数组:

[
    {"Dir 01" => {:private => false}},
    {"Dir 01" => {:private => true}},
    {"Dir 01" => {"Dir 01 01" => {:private => false}}},
    {"Dir 01" => {"Dir 01 02" => {:private => false}}},
    {"Dir 01" => {"Dir 01 02" => {"Dir 01 02 01" => {:private => false}}}}
]

但现在我被困了。

感谢。

1 个答案:

答案 0 :(得分:2)

您可以使用递归来获得所需的结果。这样做的好处是它允许在期望的结果中进行任意级别的嵌套。

<强>代码

def recurse(arr)
  arr.group_by { |a, _| a.first }
      each_with_object([]) do |(k, a), hashes|
        _, private = a.find { |titles,_| titles == [k] }    
        h = { title: k, private: private }
        if a.size > 1
          aa = a.map { |title, private| [title[1..-1], private] }.
                 reject { |title,_| title.empty? }
          h.update(subdirs: recurse(aa))
        end 
        hashes << h
      end
end

<强>实施例

arr = [
  [["Dir 01"], false],
  [["Dir 02"], true],
  [["Dir 01", "Dir 01 01"], false],
  [["Dir 01", "Dir 01 02"], false],
  [["Dir 01", "Dir 01 02", "Dir 01 02 01"], false]
]

recurse(arr)
  #=> [{:title=>"Dir 01", :private=>false,
  #     :subdirs=>[{:title=>"Dir 01 01", :private=>false},
  #                {:title=>"Dir 01 02", :private=>false,
  #                 :subdirs=>[{:title=>"Dir 01 02 01", :private=>false}]
  #                }
  #               ]
  #    },
  #    {:title=>"Dir 02", :private=>true}
  #   ]

arr += [
  [["Dir 01", "Dir 01 02", "Dir 01 02 01", "Dir 01 02 01 99"], true],
  [["Dir 01", "Dir 01 02", "Dir 01 02 01", "Dir 01 02 01 42"], false],
  [["Dir 01", "Dir 01 02", "Dir 01 02 02"], false],
  [["Dir 01", "Dir 01 02", "Dir 01 02 02", "Dir 01 02 02 17"], true],
  [["Dir 01", "Dir 01 02", "Dir 01 02 02", "Dir 01 02 02 31"], false]
]
  #=> [[["Dir 01"], false],
  #    [["Dir 02"], true],
  #    [["Dir 01", "Dir 01 01"], false],
  #    [["Dir 01", "Dir 01 02"], false],
  #    [["Dir 01", "Dir 01 02", "Dir 01 02 01"], false],
  #    [["Dir 01", "Dir 01 02", "Dir 01 02 01", "Dir 01 02 01 99"], true],
  #    [["Dir 01", "Dir 01 02", "Dir 01 02 01", "Dir 01 02 01 42"], false],
  #    [["Dir 01", "Dir 01 02", "Dir 01 02 02"], false],
  #    [["Dir 01", "Dir 01 02", "Dir 01 02 02", "Dir 01 02 02 17"], true],
  #    [["Dir 01", "Dir 01 02", "Dir 01 02 02", "Dir 01 02 02 31"], false]] 

recurse arr
  #=> [
  #    {:title=>"Dir 01", :private=>false, 
  #     :subdirs=>[
  #       {:title=>"Dir 01 01", :private=>false},
  #       {:title=>"Dir 01 02", :private=>false,
  #        :subdirs=>[
  #          {:title=>"Dir 01 02 01", :private=>false,
  #           :subdirs=>[
  #             {:title=>"Dir 01 02 01 99", :private=>true},
  #             {:title=>"Dir 01 02 01 42", :private=>false}
  #           ]
  #          },
  #          {:title=>"Dir 01 02 02", :private=>false,
  #           :subdirs=>[
  #             {:title=>"Dir 01 02 02 17", :private=>true},
  #             {:title=>"Dir 01 02 02 31", :private=>false}
  #           ]
  #          }
  #        ]
  #       }
  #     ]
  #    },
  #    {:title=>"Dir 02", :private=>true}
  #   ] 

<强>解释

(正在建设......)