【发布时间】:2013-07-12 18:24:55
【问题描述】:
我正在尝试编写一个函数来将带有路径信息的平面数组转换为该数组的树表示。
我们的目标是把一个数组变成如下:
[
{ :name => "a", :path => [ 'a' ] },
{ :name => "b", :path => [ 'a', 'b' ] },
{ :name => "c", :path => [ 'a', 'b', 'c' ] },
{ :name => "d", :path => [ 'a', 'd' ] },
{ :name => "e", :path => [ 'e' ] }
]
变成这样:
[{:node=>{:name=>"a", :path=>["a"]},
:children=>
[{:node=>{:name=>"b", :path=>["a", "b"]},
:children=>
[{:node=>{:name=>"c", :path=>["a", "b", "c"]}, :children=>[]}]},
{:node=>{:name=>"d", :path=>["a", "d"]}, :children=>[]}]},
{:node=>{:name=>"e", :path=>["e"]}, :children=>[]}]
我得到的最接近的结果是使用以下代码:
class Tree
def initialize
@root = { :node => nil, :children => [ ] }
end
def from_array( array )
array.inject(self) { |tree, node| tree.add(node) }
@root[:children]
end
def add(node)
recursive_add(@root, node[:path].dup, node)
self
end
private
def recursive_add(parent, path, node)
if(path.empty?)
parent[:node] = node
return
end
current_path = path.shift
children_nodes = parent[:children].find { |child| child[:node][:path].last == current_path }
unless children_nodes
children_nodes = { :node => nil, :children => [ ] }
parent[:children].push children_nodes
end
recursive_add(children_nodes, path, node)
end
end
flat = [
{ :name => "a", :path => [ 'a' ] },
{ :name => "b", :path => [ 'a', 'b' ] },
{ :name => "c", :path => [ 'a', 'b', 'c' ] },
{ :name => "d", :path => [ 'a', 'd' ] },
{ :name => "e", :path => [ 'e' ] }
]
require 'pp'
pp Tree.new.from_array( flat )
但它非常冗长,我觉得它对于非常大的集合可能不是很有效。
在 ruby 中实现这一目标的最简洁和最有效的方法是什么?
【问题讨论】:
-
发布你拥有的东西,即使你认为它不好。
-
请不要在问题中使用无法解释的方法或变量。
path是什么? -
@sawa 抱歉,打错了。路径是一个符号。
-
我认为你应该尝试简化你的树。例如如果名称是唯一的,则可以使用名称作为关键字,以便您轻松搜索。
-
@AndrewMarshall 感谢您的指点,我添加了我当前的来源。