递归过滤嵌套树形结构:筛选指定Friend节点并保留层级
树形结构筛选:保留层级且仅保留指定Friend节点
现有层级可变的嵌套树形结构,需求是筛选出包含指定Friend(如FRIEND_3)的节点,同时保留完整树形层级——过滤掉无符合条件子节点的父节点。但当前实现的filterTree函数仅能判断节点是否包含目标Friend,却会保留该节点下所有Friend,无法只保留目标项。
原问题代码
function filterTree(tree, friendName) { const filtered = tree.filter(node => { if (node.friends) { return node.friends.some(friend => friend.name === friendName); } else if (node.children) { node.children = filterTree(node.children, friendName); return node.children.length > 0; } return false; }); return filtered; }
问题分析
- 未过滤friends数组:原函数仅通过
some判断节点是否存在目标Friend,以此决定是否保留节点,但并未对friends数组本身进行过滤,导致节点保留后仍包含所有Friend。 - 修改原始数据:直接赋值
node.children = ...会修改原始树形结构,可能引发意外副作用。
修正后的实现
function filterTree(tree, friendName) { return tree.map(node => { // 递归处理子节点,得到过滤后的子节点列表 const filteredChildren = node.children?.length ? filterTree(node.children, friendName) : []; // 过滤当前节点的friends数组,只保留目标Friend const filteredFriends = node.friends?.length ? node.friends.filter(f => f.name === friendName) : []; // 判断是否保留当前节点:自身有目标Friend,或有符合条件的子节点 const shouldKeep = filteredFriends.length > 0 || filteredChildren.length > 0; if (!shouldKeep) return null; // 返回新节点,避免修改原始数据 const newNode = { ...node }; if (filteredFriends.length) newNode.friends = filteredFriends; if (filteredChildren.length) newNode.children = filteredChildren; return newNode; }).filter(Boolean); // 移除未被保留的节点(null) }
关键优化点
- 独立过滤friends:对每个节点的
friends数组单独过滤,仅保留名字匹配的项。 - 不污染原始数据:通过扩展运算符
...node创建新节点,所有修改都在新对象上进行,原始树形结构不受影响。 - 明确保留逻辑:节点只有在自身包含目标Friend,或者有经过过滤后非空的子节点时,才会被保留。
- 清理无效节点:用
filter(Boolean)过滤掉map中返回的null,确保结果仅包含符合条件的层级。
测试示例
原始树形结构
[ { "name": "BASE_PARENT_1", "children": [ { "name": "SUB_PARENT_1", "children": [ { "name": "CHILDREN_1", "friends": [ { "name": "FRIEND_1", "description": "Lorem ipsum" }, { "name": "FRIEND_2", "description": "Lorem ipsum" } ] } ] }, { "name": "SUB_PARENT_2", "children": [] } ] }, { "name": "BASE_PARENT_2", "children": [ { "name": "SUB_PARENT_1_2", "children": [ { "name": "CHILDREN_1", "friends": [ { "name": "FRIEND_1", "description": "Lorem ipsum" }, { "name": "FRIEND_3", "description": "Lorem ipsum" } ] } ] }, { "name": "SUB_PARENT_2_2", "children": [] } ] } ]
筛选FRIEND_3后的结果
调用filterTree(tree, "FRIEND_3"),得到如下结果:
[ { "name": "BASE_PARENT_2", "children": [ { "name": "SUB_PARENT_1_2", "children": [ { "name": "CHILDREN_1", "friends": [ { "name": "FRIEND_3", "description": "Lorem ipsum" } ] } ] } ] } ]
内容的提问来源于stack exchange,提问作者yanis barouzz
相关产品推荐
相关产品推荐

