ruby中的对象树遍历

ruby中的对象树遍历,ruby,Ruby,所以。。。我有以下资料: 具有从.xml文件检索的多个属性的类。如果对象是一个条件(它有两个子项)及其名称,则可以使用这些属性。基本上,对象的子属性是其子对象的名称 .xml如下所示: <object-2> <name>Object - 2</name> <yesChild>Object - 3</yesChild> <noChild>Object - 4</noChild> <

所以。。。我有以下资料:

具有从.xml文件检索的多个属性的类。如果对象是一个条件(它有两个子项)及其名称,则可以使用这些属性。基本上,对象的子属性是其子对象的名称

.xml如下所示:

<object-2>
     <name>Object - 2</name>
     <yesChild>Object - 3</yesChild>
     <noChild>Object - 4</noChild>
</object-2>

对象2
对象-3
对象-4
如果noChild为空,则表示该对象不是条件。从.xml检索的所有对象都存储到一个数组中

我需要的是以某种方式从中创建一棵树,并确定可以采取的所有路径,以便到达数组中的最后一个元素。该算法不需要遍历所有节点,只需要遍历到达数组最后一个元素所需的节点

例如:

我们有4个对象:X1、X2、X3和X4,其中X1是一个条件,X2和X3是它的子对象,那么我们将有两条路径,从X1开始,到X4结束。 路径1:X1->X2->X4 路径2:X1->X3->X4


谢谢。

既然解析后没有显示数据的格式,我猜:)下面是我将如何将解析后的数据存储在ruby对象中(为了清晰起见,使用新型哈希键语法):

然后,可以递归地进行树遍历。只要您的数组不是几千个元素长,这就可以正常工作

def tree(object_number, list)
  if object_number == list.size
    [[object_number]]
  else
    list[object_number-1].values.map { |obj_num|
      tree(obj_num,list)
    }.inject{|a,b| a+b}.map{|l| [object_number] + l}
  end
end
现在调用函数:

tree(1,data)
  => [[1, 2, 4], [1, 3, 4]]
data = [ {yes: 2, no: 3}, {yes: 4, no:5}, {yes:5, no:4}, {yes:5}, {yes: -1} ]
tree(1,data)
  => [[1, 2, 4, 5], [1, 2, 5], [1, 3, 5], [1, 3, 4, 5]]
工作原理:构建此列表的最简单方法是向后,因为我们只知道到达所有路径末尾的路径数。因此,这段代码始终遵循引用,当它到达最后一个对象时,它将以单个元素二维数组的形式返回它

tree(5,list)
  => [[5]]
在递归的每一级,它都会获取递归调用的结果(作为列表列表返回),并将自己的对象号预先添加到每个内部列表中。因此,请按照树的备份:

tree(4,list) # prepends 4 to tree(5)
  => [[4,5]]
tree(3,list) # prepends 3 to tree(4) and tree(5)
  => [[3,4,5],[3,5]]
tree(2,list) # prepends 2 to tree(4) and tree(5)
  => [[2,4,5],[2,5]]
tree(1,list) # prepends 1 to tree(2) and tree(3)
  => [[1, 2, 4, 5], [1, 2, 5], [1, 3, 5], [1, 3, 4, 5]]
如果列表的长度可能足以使堆栈溢出,那么在没有递归的情况下总是可以做到这一点。递归只是解决这个特殊问题的最简单方法

tree(4,list) # prepends 4 to tree(5)
  => [[4,5]]
tree(3,list) # prepends 3 to tree(4) and tree(5)
  => [[3,4,5],[3,5]]
tree(2,list) # prepends 2 to tree(4) and tree(5)
  => [[2,4,5],[2,5]]
tree(1,list) # prepends 1 to tree(2) and tree(3)
  => [[1, 2, 4, 5], [1, 2, 5], [1, 3, 5], [1, 3, 4, 5]]