我正在学习rails并且遇到了我想要使用的以下代码。有问题的代码是John F Miller(第一个答案)在以下链接中的答案: How to render all records from a nested set into a real html tree
def tree_from_set(set) #set must be in order
buf = START_TAG(set[0])
stack = []
stack.push set[0]
set[1..-1].each do |node|
if stack.last.lft < node.lft < stack.last.rgt
if node.leaf? #(node.rgt - node.lft == 1)
buf << NODE_TAG(node)
else
buf << START_TAG(node)
stack.push(node)
end
else#
buf << END_TAG
stack.pop
retry
end
end
buf <<END_TAG
end
def START_TAG(node) #for example
"<li><p>#{node.name}</p><ul>"
end
def NODE_TAG(node)
"<li><p>#{node.name}</p></li>"
end
def END_TAG
"</li></ul>"
end
我不确定以下情况,并希望得到任何指导。
我看到这将循环“set”将每个项目分配给对象“node”但是我无法确定[1 ..- 1]的作用。
set[1..-1].each do |node|
遵循逻辑我无法理解从数组“stack”中删除最后一项的目的
stack.pop
在1.9之后的ruby中不再支持此上下文中的此命令。我相信目的是回到循环的开始并重复。
retry
答案 0 :(得分:1)
A&#34;子阵列&#34;除了第0个元素之外的所有元素。
Ruby中的负数组索引-x
是length-x
的缩写。也就是说,-1
&#39; st元素是最后一个元素。范围1..-1
是&#34;首先是#34;但由于数组在Ruby中为零索引,这意味着&#34;除了第0个元素之外的所有元素&#34;。
堆栈保持&#34;你有多深&#34;,更确切地说,你目前在哪些元素。当检查下一个元素时,如果你&#34;熄灭&#34;,你应该关闭在添加当前项目之前列出你离开(可能是多次!)。
至于retry
:我认为它应该是redo
。如果你走出去,你必须确保你关闭你所拥有的每个列表:每次迭代从堆栈中弹出一次,关闭最近的列表并循环它,直到你在堆栈的顶部元素内,在上下文中要插入的当前节点。
实际上,代码假设您只有一棵树set[0]
的根。通过向第6行添加一个检查(使用||
),如果堆栈为空,则消除此缺陷,需要手动推送set[0]
,从而将其从循环中排除。 因为如果堆栈是空的,那么你处于包含所有内容的超空间,所以你不应该费心去比较任何东西。这使您可以从一个列表中呈现多个元素树(可能没有共同的根)。
我相信对此的清洁解决方案是一个递归的解决方案,取代&#34;自制堆栈&#34;使用Ruby的调用堆栈。尽管如此,我无法在这方面做出太快的解决方案。