如何递归移除对象数组中重复的id=3对象,仅保留id=2子项中的该对象
移除根层级重复节点的可行实现思路
针对你提供的嵌套对象数组,要移除根层级中已作为子节点存在的id=3对象,以下是几种实用的实现思路:
思路1:先收集子树所有ID,再过滤根节点
核心逻辑是先把所有嵌套子节点的ID收集起来,再从根数组中剔除那些ID已存在于子树中的元素。
// 递归收集所有子树节点的ID function collectChildNodeIds(nodes) { const idSet = new Set(); const traverse = (node) => { node.children.forEach(child => { idSet.add(child.id); traverse(child); }); }; nodes.forEach(traverse); return idSet; } // 执行过滤 const childIds = collectChildNodeIds(data); const filteredData = data.filter(item => !childIds.has(item.id));
思路2:闭包内维护ID集合,先标记子节点再过滤根节点
利用闭包保存已出现的子节点ID,先遍历所有子节点完成标记,最后对根数组做过滤。
function removeDuplicateRoots(data) { const existingChildIds = new Set(); // 遍历所有子节点,标记已存在的ID const markChildIds = (nodes) => { nodes.forEach(node => { node.children.forEach(child => { existingChildIds.add(child.id); markChildIds([child]); }); }); }; markChildIds(data); // 过滤根节点,移除已在子树中出现的ID return data.filter(node => !existingChildIds.has(node.id)); } const result = removeDuplicateRoots(data);
思路3:深度优先遍历,边处理子树边构建结果
在遍历过程中先处理子节点并标记ID,再判断当前根节点是否需要保留,一步完成结果构建,避免额外的遍历步骤。
function filterDuplicateRootNodes(data) { const existingIds = new Set(); const result = []; const processSubtree = (node) => { // 先递归处理子节点,标记所有子节点ID node.children.forEach(child => { existingIds.add(child.id); processSubtree(child); }); }; data.forEach(node => { processSubtree(node); // 根节点ID未在子树中出现过,才加入结果 if (!existingIds.has(node.id)) { result.push(node); } }); return result; } const result = filterDuplicateRootNodes(data);
内容的提问来源于stack exchange,提问作者Đạt Huỳnh
相关产品推荐
相关产品推荐

