从模型关系创建未知深度的数组

时间:2014-03-09 22:27:01

标签: ruby

所以这似乎是一个简单的问题,但我很难找到解决方案。

我有一个页面列表,一些页面有子页面,其中一些子页面有自己的子页面。我想创建一种按照子页面顺序列出所有页面的方法。

我的目标是这个输出:

page_1
  page_1a
page_2
  page_2a
  page_2b
    page_2bi
    page_2bii
    page_2biii
  page_2c
page_3
page_4
page_5

(我正在寻找的实际输出是一个数组,然后我可以在我的视图中打印出来。)

如果我使用嵌套的each语句,这将非常容易,但我想要一些与嵌套深度无关的东西。无论嵌套的级别数是多少,我都需要能产生正确输出的东西。

我已经找到了解决方案,并提出了以下代码。这段代码的问题在于,一旦它嵌入,它就找不到嵌套页面的父级的剩余兄弟 - 换句话说,它在找到嵌套页面后停止并移动到下一个顶级页面。 / p>

def print_page_hierarchy
  output = []
  Page.top_level.each do |p|
    level = 0
    keep_looping = true
    output << [p.title]
    while keep_looping
      if p.children?
        level += 1
        nested_pages = p.children
        for p in nested_pages
          output << [" "*(level*2)+p.title]
          if p.children?
            nested_pages = p.children # p.children returns an array of child pages
            keep_looping = true
            break
          end
        end
      else
        keep_looping = false
      end
    end
  end
  output
end

我该如何使这项工作?

或者有更好的方法来解决这个问题吗?

修改

输入是一系列关联。页面包含parent_page_id,其方法为parentchildren。我没有初始数组,只有关联。 这并不重要,因为问题是如何处理递归。为简单起见,您可以假设这是一个数组。

1 个答案:

答案 0 :(得分:1)

准备一些输入。我假设你有一个节点数组,每个节点都有一个名字和子节点:

class Node < Struct.new(:name, :children); end
nodes = [ Node.new(:page_1, [ Node.new(:page_1a) ]),
          Node.new(:page_2, [ Node.new(:page_2a),
                              Node.new(:page_2b, [ Node.new(:page_2bi),
                                                   Node.new(:page_2bii),
                                                   Node.new(:page_2biii) ]),
                              Node.new(:page_2c) ]),
          Node.new(:page_3),
          Node.new(:page_4),
          Node.new(:page_5) ]

递归方法:

def print_page_hierarchy(nodes, indent = 0)
  return unless nodes   # stops the recursion if there are no nodes

  nodes.each do |node|
    puts "#{'  ' * indent}#{node.name}"
    # here is the list of all children generated, do not care about how
    # deep the subtree is, cause recursion...
    print_page_hierarchy(node.children, indent + 1)
  end
end

测试

print_page_hierarchy(nodes)
# => page_1
#      page_1a
#    page_2
#      page_2a
#      page_2b
#        page_2bi
#        page_2bii
#        page_2biii
#      page_2c
#    page_3
#    page_4
#    page_5