You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS递归过滤数组:移除指定ID元素及其所有子元素的实现求助

解决方案

我们可以分两步实现需求:先找出所有需要排除的节点ID(目标ID及其所有子孙节点),再过滤原数组得到结果。

步骤1:构建父节点映射

先把原数组转换成父ID -> 子节点列表的映射,方便快速查找某个节点的所有子节点:

const buildParentMap = (arr) => {
  const map = {};
  arr.forEach(item => {
    if (item.parent) {
      const parentId = item.parent.id;
      if (!map[parentId]) {
        map[parentId] = [];
      }
      map[parentId].push(item.id);
    }
  });
  return map;
};

步骤2:递归收集所有需要排除的ID

通过递归遍历,收集目标ID及其所有子孙的ID:

const collectExcludedIds = (targetId, parentMap, excluded = new Set()) => {
  excluded.add(targetId);
  // 获取当前节点的所有子节点ID
  const childrenIds = parentMap[targetId] || [];
  // 递归处理每个子节点
  childrenIds.forEach(childId => {
    collectExcludedIds(childId, parentMap, excluded);
  });
  return excluded;
};

步骤3:主函数实现

整合上面两个函数,过滤原数组:

const filterTreeNodes = (originalArray, excludeId) => {
  const parentMap = buildParentMap(originalArray);
  const excludedIds = collectExcludedIds(excludeId, parentMap);
  // 过滤出不在排除列表中的节点
  return originalArray.filter(item => !excludedIds.has(item.id));
};

测试示例

用你提供的数组测试:

const originalArray = [
 {id: 1, name: 'Parent1'},
 {id: 2, name: 'Child1', parent: {id: 1, name: 'Parent1'}},
 {id: 3, name: 'Child2', parent: {id: 1, name: 'Parent1'}},
 {id: 4, name: 'GrandChild1', parent: {id: 3, name: 'Child2'}},
 {id: 5, name: 'GrandChild2', parent: {id: 3, name: 'Child2'}}
];

// 排除id=3的节点及其子孙
console.log(filterTreeNodes(originalArray, 3));
// 输出结果:
// [
//  {id: 1, name: 'Parent1'},
//  {id: 2, name: 'Child1', parent: {id: 1, name: 'Parent1'}}
// ]

说明

  • 用Set存储排除ID是为了提高查找效率,避免重复添加
  • 映射表的构建只需要一次,递归过程可以快速定位子节点,避免每次遍历整个数组查找子节点,性能更优
  • 如果原数组很大,这种方式比每次递归遍历整个数组要高效得多

内容的提问来源于stack exchange,提问作者Sergey Grenaderov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 00:47:03