递归树构建函数仅映射一个子项

时间:2018-04-12 02:28:20

标签: ruby recursion

我试图以递归方式构建一棵树。下面的类通过递归调用.children getter来将树构建为Hash。

class Tree
  attr_reader :root

  def initialize(uri:)
    @root     = Article.new(uri: uri)
    @children = nil
  end

  def children(depth: 3, article_children: self.root.child_links)
    @children ||= article_children.map do |uri|
      puts "URI: #{uri}"
      if (depth == 0)
        return Article.new(uri: uri)
      else
        article = Article.new(uri: uri)
        return { article => self.children(depth: depth - 1, article_children: article.child_links) }
      end
    end

    puts JSON.pretty_generate(@children)
    return @children
  end
end

我希望生成的JSON看起来像这样:

{
      "#<Article:0x00007ff1a33c06d0>": {
        "#<Article:0x00007ff1a345e920>": {
          "#<Article:0x00007ff1a3989418>": ["#<Article:0x00007ff1a423f698>", ...]
        },
        "#<Article:0x00007ff1a345e920>": {
          "#<Article:0x00007ff1a3989418>": ["#<Article:0x00007ff1a423f698>", ...]
        },
        "#<Article:0x00007ff1a345e920>": {
          "#<Article:0x00007ff1a3989418>": ["#<Article:0x00007ff1a423f698>", ...]
        },
        "#<Article:0x00007ff1a345e920>": {
          "#<Article:0x00007ff1a3989418>": ["#<Article:0x00007ff1a423f698>", ...]
        },
        "#<Article:0x00007ff1a345e920>": {
          "#<Article:0x00007ff1a3989418>": ["#<Article:0x00007ff1a423f698>", ...]
        },
      }
    }
}

然而,美化的JSON最终看起来像这样:

{
  "#<Article:0x00007ff1a33c06d0>": {
    "#<Article:0x00007ff1a345e920>": {
      "#<Article:0x00007ff1a3989418>": "#<Article:0x00007ff1a423f698>"
    }
  }
}

puts "URI: #{uri}输出中的article.children.map

URI: https://child.uri.org/example/uri
URI: https://child.uri.org/example/uri1
URI: https://child.uri.org/example/uri2
URI: https://child.uri.org/example/uri3

每个URI都是每个文章对象的第一个子URI。

为什么map只处理第一个元素,而不是整个数组?

1 个答案:

答案 0 :(得分:1)

块中的return关键字不仅会结束块,还会结束父函数(在本例中为def children)。

因此,您没有按预期返回map的结果,而是在第一次迭代后返回完整的函数。它仍将触发递归调用,但在每次递归调用中都会发生相同的行为。这就是您在结果中看到嵌套的原因,但每个级别只有一个元素而不是数组。

因此,您只需删除return字词,并保持其他所有内容相同即可。请注意,除非您强行提早从某个方法返回,否则return无论如何都不是必需的。

或者,您可以将return替换为nextreturn是可枚举函数中使用的特殊关键字,用于下一次迭代。与{{1}}类似,它可以传递一个参数,该参数成为该迭代的块的返回值。有关详细信息,请参阅http://www.linuxtopia.org/online_books/programming_books/ruby_tutorial/Ruby_Expressions_Break_Redo_and_Next.html或其他资源。