编辑:除了针对该问题的其他解决方案之外,我还热衷于了解这种递归或递归问题是否具有模式,我使用过的技术是否有名称(即通过引用基于对对象的更改中断将来的递归)此技术在其他一些情况下有用吗?
我在nAry树中寻找一个值,一旦找到它,我想破坏递归(还有其他基本情况可以破坏该示例)。代码如下所示:
function getCommentById(root, commentId, foundComment) {
if (root.id === commentId) {
return root;
}
if (foundComment.comment) {
return foundComment.comment;
}
if (!root.comments) {
return foundComment.comment;
} else {
for (let i = 0; i < root.comments.length; i++) {
foundComment.comment = getCommentById(
root.comments[i],
commentId,
foundComment
);
}
}
return foundComment.comment;
}
基本上,我正在浏览嵌套评论,以按其ID查找评论。
我必须遍历当前注释的所有子级,然后递归调用此函数。假设我在当前注释的child1中找到了该注释,我不想再递归而只是中断递归,但是循环将继续到下一个兄弟并递归。 这种事情在二叉树中很容易,因为我可以做类似的事情
return getCommentById(left) || getCommentById(right)
但是我在这里实现相同的逻辑时遇到了麻烦,因为我们需要以某种方式存储每个子调用的结果,并基于此决定是否找到值。因此,我的解决方案使用一个辅助变量来表示何时找到该值。我发现这应该是一个对象,而不是变量,以便在随后的child1到child2的递归调用中可以看到值的变化。如果我只是在child1递归中使用了一个标志并将其设置为true,那将是不可能的,因为那样的话,child2递归仍将标志视为false并继续递归。
有没有更好的方法? 使用对象引用破坏递归的这种技术是否有名称?还有什么可以实现的呢?
编辑:测试数据集
const post = {
id: "post1",
title: "Sample Post 1",
description: "This is a sample post",
createdBy: "user1",
createdAt: new Date(),
comments: [
{
id: "post1comment1",
text: "This is comment 1",
userId: "user1",
timestamp: new Date().setFullYear(2018),
comments: [
{
id: "post1comment1.1",
text: "This is sub comment 1 of comment 1",
userId: "user2",
timestamp: new Date()
}
]
},
{
id: "post1comment2",
text: "This is comment 2",
userId: "user4",
timestamp: new Date()
},
{
id: "post1comment3",
text: "This is comment 3",
userId: "user4",
timestamp: new Date()
}
]
},
用法:
const foundComment = { comment: null };
getCommentById(post, "post1comment1.1", foundComment);
答案 0 :(得分:1)
您可以使用基于堆栈的迭代树遍历方法。这是基本概念:
function find_thing(root) {
var stack = [ root ];
while(0 < stack.length) {
var current_thing = stack.pop();
if(is_the_thing(current_thing)) {
return current_thing;
}
stack = stack.concat(current_thing.AllMyKids());
}
return null;
}
答案 1 :(得分:1)
您可以直接将节点作为结果,而无需通过对象引用将其返回。
function getCommentById(root, commentId) {
var temp;
if (root.id === commentId) return root;
(root.comments || []).some(node => temp = getCommentById(node, commentId))
return temp;
}
const
post = { id: "post1", title: "Sample Post 1", description: "This is a sample post", createdBy: "user1", createdAt: new Date(), comments: [{ id: "post1comment1", text: "This is comment 1", userId: "user1", timestamp: new Date().setFullYear(2018), comments: [{ id: "post1comment1.1", text: "This is sub comment 1 of comment 1", userId: "user2", timestamp: new Date() }] }, { id: "post1comment2", text: "This is comment 2", userId: "user4", timestamp: new Date() }, { id: "post1comment3", text: "This is comment 3", userId: "user4", timestamp: new Date() }] },
result = getCommentById(post, "post1comment1.1");
console.log(result);
答案 2 :(得分:1)
添加此内容是为了完整性。 基于对我要解决的问题的更好理解,我能够将代码简化为:
function getCommentByIdSimple(root, commentId) {
if (!root) {
return null;
}
if (root.id === commentId) {
return root;
} else {
let node;
if (!root.comments) {
return null;
}
for (let i = 0; i < root.comments.length; i++) {
if ((node = getCommentByIdSimple(root.comments[i], commentId))) {
return node;
}
}
}
return null;
}
我要解决的问题是找到所需注释后如何退出for
循环。在上面的实现中,我检查是否发现node
我只是返回node
,所以返回后的进一步迭代将被忽略。
此方法的灵感来自: n-ary tree searching function