Javascript 如何从嵌套对象数组中递归删除特定对象?

Javascript 如何从嵌套对象数组中递归删除特定对象?,javascript,ecmascript-6,Javascript,Ecmascript 6,数据: 我需要从该数据中删除“id”:5,我尝试了以下方法: var data = [ { "name":"list1", "type":"list", "id":1, "child":[ { "name":"list2", "type":"subList", "id":2, "child":[

数据:

我需要从该数据中删除“id”:5,我尝试了以下方法:

    var data = [ 
   { 
      "name":"list1",
      "type":"list",
      "id":1,
      "child":[ 
         { 
            "name":"list2",
            "type":"subList",
            "id":2,
            "child":[ 
               { 
                  "name":"list3",
                  "type":"subList",
                  "id":3
               },
               { 
                  "name":"list4",
                  "type":"list",
                  "id":4,
                  "child":[ 
                     { 
                        "name":"list5",
                        "type":"list",
                        "id":5
                     }
                  ]
               }
            ]
         },
         { 
            "name":"list6",
            "type":"subList",
            "id":6
         }
      ]
   },
   { 
      "name":"list I",
      "type":"list",
      "id":7
   }
]
最终输出将没有id:5,在某些情况下,第一个列表id:1也可以擦除。要递归地简化这个过程,它可能没有N个子列表,必须循环遍历每个列表并删除它?

如果不循环遍历数组,没有简单(非黑客)的方法来删除元素

您需要首先筛选数据数组,然后映射其余条目,并递归筛选其
子属性,例如:

函数removedeep(数据,idToRemove){
const filtered=data.filter(entry=>entry.id!==idToRemove);
返回筛选的.map(条目=>{
如果(!entry.child)返回条目;
返回{…entry,child:removeddeep(entry.child,idToRemove)};
});
}
var data=[{“name”:“list1”,“type”:“list”,“id”:1,“child”:[{“name”:“list2”,“type”:“subList”,“id”:2,“child”:[{“name”:“list3”,“type”:“subList”,“id”:3},{“name”:“list4”,“type”:“list”,“id”:4,“child”:[{“name”:“list5”,“type”:“list”,“id”:5}]}}}},{“name”:“list6”,“type”:“subList”,“id”:6},{“name”:“list”,“type”:“list I”,“type”:“list”:“列表”,“id”:7}];
函数removeIdDeep(数据,idToRemove){
const filtered=data.filter(entry=>entry.id!==idToRemove);
返回筛选的.map(条目=>{
如果(!entry.child)返回条目;
返回{…entry,child:removeddeep(entry.child,idToRemove)};
});
}

console.log(removeddeep(data,5));
您可以创建一个递归函数,为每个
子数组应用过滤器,如下所示:

data.filter(function f(o) {
  return o.id !== 5 ||
         o.child && (o.child.filter(f)).length
})
var数据=[
{ 
“名称”:“列表1”,
“类型”:“列表”,
“id”:1,
“儿童”:[
{ 
“名称”:“列表2”,
“类型”:“子列表”,
“id”:2,
“儿童”:[
{ 
“名称”:“列表3”,
“类型”:“子列表”,
“id”:3
},
{ 
“名称”:“列表4”,
“类型”:“列表”,
“id”:4,
“儿童”:[
{ 
“名称”:“列表5”,
“类型”:“列表”,
“id”:5
}
]
}
]
},
{ 
“名称”:“列表6”,
“类型”:“子列表”,
“id”:6
}
]
},
{ 
“姓名”:“名单一”,
“类型”:“列表”,
“id”:7
}
]
常量过滤器数据=(el)=>{
如果(el.id==5){
返回错误
}
如果(儿童){
el.child=el.child.filter(filterData)
}
返回真值
}
const filtered=data.filter(filterData)

console.log(过滤)
不直接更改子项,更好地传播

const filterData = (el) => {
  if(el.id === 5) {
    return false
  }

  if(el.child) {
    el.child = el.child.filter(filterData)
  }

  return true
}

const filtered = data.filter(filterData)

因此,如果一个孩子有你想要删除的ID,应该删除家长?或者只是孩子?如果家长包含删除的项目,我需要显示警报以确认用户同时删除家长和孩子Bad解决方案,它将更改原始中的孩子道具objects@DmitryReutov您还可以使用扩展运算符(如您在回答中所建议的)获取像这样的
[…data].filter(filterData)的
数据的临时数组
这并不是毫无意义的,它被称为数组克隆,你可以这样做,以避免改变原始数组,如果OP当然关心它,而他似乎并不关心。因此,既然OP只想删除这些特定元素,那么不管原始数组是否被改变,因此即使不进行克隆,我的解决方案也是如此不坏。克隆对象和数组的问题没有问题。我不理解为什么我们需要这个返回{…entry,child:removeddeep(entry.child,idToRemove)};相反,只需返回removeddeep(entry.child,idToRemove)@Learntocode它将复制条目并用
removeddeep(entry.child,idToRemove)替换子属性
-如果只返回最后一部分,则结果将是嵌套数组,叶节点除外(用于处理它)谢谢。如果一个父项应该被删除,但它包含子项,那么我应该指出一个用户说like child也将被删除。@Learntocode我添加了一个小例子,如何添加一个
确认
提示,让用户确认删除。你能解释一下{…elem,child:deleteObject(elem.child,id)}这条线please@Learntocode我们分散元素以不更改原始元素,因此您将获得原始数组的副本,而不删除元素,但原始数组将保持原样
deleteObject = (arr, id) => {
   return arr
      .filter(elem => elem.id !== id)
      .map(elem => elem.child 
           ? {
         ...elem,
         child: deleteObject(elem.child, id)
      } : elem)   
}