我试图以递归方式构建一棵树。下面的类通过递归调用.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只处理第一个元素,而不是整个数组?
答案 0 :(得分:1)
块中的return
关键字不仅会结束块,还会结束父函数(在本例中为def children
)。
因此,您没有按预期返回map
的结果,而是在第一次迭代后返回完整的函数。它仍将触发递归调用,但在每次递归调用中都会发生相同的行为。这就是您在结果中看到嵌套的原因,但每个级别只有一个元素而不是数组。
因此,您只需删除return
字词,并保持其他所有内容相同即可。请注意,除非您强行提早从某个方法返回,否则return
无论如何都不是必需的。
或者,您可以将return
替换为next
,return
是可枚举函数中使用的特殊关键字,用于下一次迭代。与{{1}}类似,它可以传递一个参数,该参数成为该迭代的块的返回值。有关详细信息,请参阅http://www.linuxtopia.org/online_books/programming_books/ruby_tutorial/Ruby_Expressions_Break_Redo_and_Next.html或其他资源。