如何同时过滤树形嵌套对象并转换结果?
问题描述
我有如下树形结构的数据:
const tree = [ { slug: 'item-1', children: [ { slug: 'item-1-1', children: [ { slug: 'item-1-1-1' }, { slug: 'item-1-1-2' } ], }, ], }, { slug: 'item-2', children: [ { slug: 'item-2-1', children: [ { slug: 'item-2-1-1' }, { slug: 'item-2-1-2' } ], }, ], }, ];
我需要基于slug对其进行过滤,但希望结果仅保留匹配项的直接子节点。例如,当搜索slug === "item-1"时,预期结果为:
[ { slug: "item-1", children: [ { slug: "item-1-1" } ], }, ]
由于该树形结构可能庞大且复杂,我考虑过组合使用filter()、reduce()或map()来解决,但感觉不够高效,请问该如何最优解决这个问题?
最优解决方案
针对庞大复杂的树形结构,**迭代式深度优先搜索(DFS)**是最优选择——它不会像递归那样触发栈溢出,而且能在找到目标节点后立即终止遍历,避免不必要的计算。
核心逻辑:
- 用栈模拟递归遍历过程,逐个处理节点
- 找到匹配目标slug的节点后,直接构造仅包含其直接子节点的结果结构并返回
- 遍历完成未找到匹配节点时,返回空数组
实现代码:
function filterTreeBySlug(tree, targetSlug) { const stack = [...tree]; // 初始化栈,放入根节点列表 while (stack.length > 0) { const node = stack.pop(); // 从栈顶取出节点 if (node.slug === targetSlug) { // 构造结果:保留当前节点slug,仅保留直接子节点的slug(剔除子节点的children) return [{ slug: node.slug, children: node.children?.map(child => ({ slug: child.slug })) || [] }]; } // 将子节点倒序压入栈,保证遍历顺序和递归DFS一致(可选,不影响结果正确性) if (node.children?.length) { stack.push(...[...node.children].reverse()); } } // 未找到匹配节点时返回空数组 return []; } // 测试示例 const result = filterTreeBySlug(tree, 'item-1'); console.log(result);
方案优势
- 效率最优:找到目标节点后立即终止遍历,最坏时间复杂度为O(n),实际平均效率远高于全量遍历的
filter/reduce组合 - 避免栈溢出:迭代式实现不受递归深度限制,适配任意深度的树形结构
- 内存友好:栈的空间占用仅取决于树的最大深度,远低于全量复制节点的方案
- 结果精准:直接构造需求结构,无需额外的过滤或清理步骤
内容的提问来源于stack exchange,提问作者Arman Zanjani
相关产品推荐
相关产品推荐

