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
相关产品推荐
相关产品推荐

