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

递归过滤嵌套树形结构:筛选指定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;
}

问题分析

  1. 未过滤friends数组:原函数仅通过some判断节点是否存在目标Friend,以此决定是否保留节点,但并未对friends数组本身进行过滤,导致节点保留后仍包含所有Friend。
  2. 修改原始数据:直接赋值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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 18:12:50