Javascript—递归地从树中删除特定类型的节点,但重新连接并传播符合条件的子节点
我正在JSON树Javascript—递归地从树中删除特定类型的节点,但重新连接并传播符合条件的子节点,javascript,json,recursion,tree,Javascript,Json,Recursion,Tree,我正在JSON树{name,type,[children]}上编写一个递归函数来删除特定类型的节点。但是,如果移除节点的子节点不是要移除的类型,则应将其重新附着到父节点 我遇到了以下困难: 假设我要删除以下树上的类型b: const sampleData = [{ name: "parent", type: "a", children: [{ name: "childA", type: "a",
{name,type,[children]}
上编写一个递归函数来删除特定类型的节点。但是,如果移除节点的子节点不是要移除的类型,则应将其重新附着到父节点
我遇到了以下困难:
假设我要删除以下树上的类型b:
const sampleData = [{
name: "parent",
type: "a",
children: [{
name: "childA",
type: "a",
children: null
},{
name: "childB",
type: "b",
children: [{
name: "grandChildA",
type: "a",
children: null
},{
name: "grandChildB",
type: "a",
children: null
}]
},{
name: "childC",
type: "a",
children: null
}]
}]
父项的原始子项是[childA,childB,childC]
。
删除后,父项应该有子项[childA,孙子a,孙子b,childC]
。
然而,我得到的结果是[childA,[grandera,granderb],childC]
我知道我需要把它展开,但我不确定在复发的时候该在哪里做
下面是我现在拥有的函数(我知道我在错误的地方使用了扩展语法):
已更新 我想你可以使用reduce,我现在没有电脑来测试它,但它会是这样的
const removeType = (node, type) => {
if (node === null) {
return null;
} else {
return node.reduce((acc, child) => {
if(child["type"] === type) {
const removedChild = removeType(child["children"], type);
acc = [...acc, ...removedChild];
} else {
child.children = removeType(child["children"], type);
acc.push(child);
}
return acc;
}, []);
}
}
第二次更新
代码缩减:
const removeType = (node, type) => {
if (!node) return;
return node.reduce((acc, child) => {
if(child["type"] === type) {
const removedChild = removeType(child["children"], type);
acc = [...acc, ...removedChild];
} else {
child.children = removeType(child["children"], type);
acc.push(child);
}
return acc;
}, []);
}
已更新 我想你可以使用reduce,我现在没有电脑来测试它,但它会是这样的
const removeType = (node, type) => {
if (node === null) {
return null;
} else {
return node.reduce((acc, child) => {
if(child["type"] === type) {
const removedChild = removeType(child["children"], type);
acc = [...acc, ...removedChild];
} else {
child.children = removeType(child["children"], type);
acc.push(child);
}
return acc;
}, []);
}
}
第二次更新
代码缩减:
const removeType = (node, type) => {
if (!node) return;
return node.reduce((acc, child) => {
if(child["type"] === type) {
const removedChild = removeType(child["children"], type);
acc = [...acc, ...removedChild];
} else {
child.children = removeType(child["children"], type);
acc.push(child);
}
return acc;
}, []);
}
下面是一种使用
Array.prototype.flatMap
简化程序的方法,其中包括一些数学归纳和一些相互递归-
接受一个removeType
节点数组和一个要删除的查询类型
q
接受单个removeType1
节点和要删除的查询类型
q
const removeType=(节点,q)=>
(节点| |[]).flatMap(n=>removeType1(n,q))//
q==节点类型
? removeType(node.children)//下面是一种使用Array.prototype.flatMap
简化程序的方法,其中包括一些数学归纳和少量的相互递归-
removeType
接受一个节点数组和一个要删除的查询类型q
removeType1
接受单个节点和要删除的查询类型q
const removeType=(节点,q)=>
(节点| |[]).flatMap(n=>removeType1(n,q))//
q==节点类型
? removeType(node.children)/我认为这个答案与提供的其他答案有足够的不同,可以将它作为一个替代添加。它与Thankyou的答案具有相同的递归结构,但它简化了一个假设,即您的输入始终是一个数组,所有非nil子节点也是如此
const removeType=(节点,目标)=>
node.flatMap({type,children,…rest})=>
类型===目标
?子对象?移除类型(子对象,目标):[]
:[{…rest,type,children:children&&(removeType(children,target))}]
)
const sampleData=[{name:“parent”,type:“a”,childs:[{name:“childA”,type:“a”,childs:null},{name:“childB”,type:“b”,childs:[{name:“gendera”,type:“a”,childs:null},{name:“childC”,type:“a”,childs:null}]
控制台日志(
removeType(样本数据“b”)
)
.as console wrapper{min height:100%!important;top:0}
我认为这个答案与提供的其他答案有足够的不同,可以将其添加为替代答案。它与Thankyou的答案具有相同的递归结构,但它简化了一个假设,即您的输入始终是一个数组,所有非nil子节点也是如此
const removeType=(节点,目标)=>
node.flatMap({type,children,…rest})=>
类型===目标
?子对象?移除类型(子对象,目标):[]
:[{…rest,type,children:children&&(removeType(children,target))}]
)
const sampleData=[{name:“parent”,type:“a”,childs:[{name:“childA”,type:“a”,childs:null},{name:“childB”,type:“b”,childs:[{name:“gendera”,type:“a”,childs:null},{name:“childC”,type:“a”,childs:null}]
控制台日志(
removeType(样本数据“b”)
)
。作为控制台包装{min height:100%!important;top:0}
此返回[childA,[grandera,granderb],childC]
,仍然具有嵌套数组。非常感谢!我应该考虑使用reduce lol。这返回[childA[granda,grandb],childC]
,仍然有嵌套数组。非常感谢!我应该考虑使用reduce lol。谢谢你的回答!这很有帮助!谢谢你的回答!这很有帮助!