Javascript - 递归地从树中删除某种类型的节点,但重新附加并传播符合条件的子节点

我正在 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

    }]

}]

parent 的原始 children 是[childA, childB, childC]. 移除后,父母应该有孩子[childA, grandChildA, grandChildB, childC]。但是,我得到的结果是[childA, [grandChildA, grandChildB], childC].


我知道我需要把它分散开来,但我不确定在回避中在哪里做。


这是我现在拥有的功能(我知道我在错误的地方使用了扩展语法):


const removeType = (node, type) => {

    //if the node should not be removed    

    if (node.type !== type){

        //if the node has children, recursively call to prune children

        if (node.children && node.children.length > 0){

            node.children = [...node.children.map(child => removeType(child, type))

                                             .filter(child => child !== null)]

            return node

        }

        //if the node has no children, return the node

        else return node

    }

    //if the node should be removed

    else if (node.type === type){

        //if the node has children, recursively call, then reattach the children

        if (node.children && node.children.length > 0){

            node.children = [...node.children.map(child => removeType(child, type))

                                             .filter(child => child !== null)]

            return node.children

        }

        //

        else return null

    }

}


宝慕林4294392
浏览 225回答 3
3回答

Smart猫小萌

更新我想你可以为此使用 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;    }, []);}

慕工程0101907

我认为这个答案与提供的其他答案完全不同,可以将其添加为替代方案。它具有与 Thankyou 的答案相同的递归结构,但它简化了假设,即您的输入始终是一个数组,所有非零children节点也是如此。const removeType = (node, target) =>  node .flatMap (({type, children, ...rest}) =>    type === target      ? children ? removeType (children, target) : []      : [{...rest, type, children: children && (removeType (children, target))}]  )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}]}]console .log ( removeType (sampleData, 'b')).as-console-wrapper {min-height: 100% !important; top: 0}

猛跑小猪

Array.prototype.flatMap这是使用、一些数学归纳法和一些相互递归来简化程序的方法-removeType接受一个数组nodes和一个要删除的查询类型,qremoveType1接受单个&nbsp;node和要删除的查询类型,qconst removeType = (nodes, q) =>&nbsp; (nodes || []).flatMap(n => removeType1(n, q))&nbsp; // <-- removeType1const removeType1 = (node, q) =>&nbsp; q === node.type&nbsp; &nbsp; ? removeType(node.children)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // <-- removeType&nbsp; &nbsp; : { ...node, children: removeType(node.children, q) } // <-- removeTypeconst input =&nbsp;&nbsp; [{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}]}]&nbsp;&nbsp;const result =&nbsp; removeType(input, "b")console.log(result)输出 -[&nbsp; {&nbsp; &nbsp; "name": "parent",&nbsp; &nbsp; "type": "a",&nbsp; &nbsp; "children": [&nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; "name": "childA",&nbsp; &nbsp; &nbsp; &nbsp; "type": "a",&nbsp; &nbsp; &nbsp; &nbsp; "children": []&nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; "name": "grandChildA",&nbsp; &nbsp; &nbsp; &nbsp; "type": "a",&nbsp; &nbsp; &nbsp; &nbsp; "children": []&nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; "name": "grandChildB",&nbsp; &nbsp; &nbsp; &nbsp; "type": "a",&nbsp; &nbsp; &nbsp; &nbsp; "children": []&nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; "name": "childC",&nbsp; &nbsp; &nbsp; &nbsp; "type": "a",&nbsp; &nbsp; &nbsp; &nbsp; "children": []&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; ]&nbsp; }]请注意,这result是一个新对象,input不会因调用.removeType相互递归非常适合解决上述问题,但如果您真的只想要一个函数怎么办?const removeType = (t, q) =>&nbsp; Array.isArray(t)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// <-- array&nbsp; &nbsp; ? t.flatMap(node => removeType(node, q)): Object(t) === t&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // <-- object (node)&nbsp; &nbsp; ? q === t.type&nbsp; &nbsp; &nbsp; &nbsp; ? removeType(t.children, q)&nbsp; &nbsp; &nbsp; &nbsp; : { ...t, children: removeType(t.children, q) }: t&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // <-- else (no operation)const input =&nbsp;&nbsp; [{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}]}]&nbsp;&nbsp;const result =&nbsp; removeType(input, "b")console.log(result)输出大部分是相同的,除了注意这个是如何保存的children: null。我们的原始程序产生更正确的children: []-[&nbsp; {&nbsp; &nbsp; "name": "parent",&nbsp; &nbsp; "type": "a",&nbsp; &nbsp; "children": [&nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; "name": "childA",&nbsp; &nbsp; &nbsp; &nbsp; "type": "a",&nbsp; &nbsp; &nbsp; &nbsp; "children": null&nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; "name": "grandChildA",&nbsp; &nbsp; &nbsp; &nbsp; "type": "a",&nbsp; &nbsp; &nbsp; &nbsp; "children": null&nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; "name": "grandChildB",&nbsp; &nbsp; &nbsp; &nbsp; "type": "a",&nbsp; &nbsp; &nbsp; &nbsp; "children": null&nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; "name": "childC",&nbsp; &nbsp; &nbsp; &nbsp; "type": "a",&nbsp; &nbsp; &nbsp; &nbsp; "children": null&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; ]&nbsp; }]
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript