这比你想象的要容易,你只需要意识到一些简单的事情:
-
nil
是一个完全有效的哈希键。
- 您可以使用
nil
作为树的虚拟根,以便所有:parent_id
s 指向树上的东西。
- 您可以通过两种方式一次性遍历数组并跟踪条目:
:id
and by :parent_id
.
首先是一棵由哈希表示的树:
tree = Hash.new { |h,k| h[k] = { :title => nil, :children => [ ] } }
我们将从根到叶,因此我们只对父/子关系的子方感兴趣,因此:children
数组中的默认值。
然后一个简单的迭代填充:title
s and :children
就这样:
arr.each do |n|
id, parent_id = n.values_at(:id, :parent_id)
tree[id][:title] = n[:title]
tree[parent_id][:children].push(tree[id])
end
请注意,节点(包括父节点)是由以下命令自动创建的tree
's default_proc
第一次看到它们时,节点顺序是arr
是无关紧要的。
这让我们留下了树tree
钥匙在哪里:id
s(包括位于nil
key),值是从该点开始的子树。
然后如果你看tree[nil][:children]
剥离虚拟根,你会看到这个:
[
{ :title => "A", :children => [
{ :title => "A1", :children => [
{ :title => "A11", :children => [] },
{ :title => "12", :children => [
{ :title => "A2=121", :children => [] }
] }
] },
{ :title => "A2", :children => [
{ :title => "A21", :children => [] }
] }
] },
{ :title => "B", :children => [
{ :title => "B11", :children => [] },
{ :title => "B12", :children => [] }
] }
]
这正是您正在寻找的结构,您应该能够从那里获取它。这与您的示例响应不匹配,但那是因为您的示例arr
也没有。
你也可以说:
tree = arr.each_with_object(Hash.new { |h,k| h[k] = { :title => nil, :children => [ ] } }) do |n, tree|
#...
end
如果您更喜欢嘈杂的第一行而不是单独的tree
宣言。