Javascript—递归地从树中删除特定类型的节点,但重新连接并传播符合条件的子节点

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",

我正在JSON树
{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。谢谢你的回答!这很有帮助!谢谢你的回答!这很有帮助!