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

如何在JS/TS中获取深层嵌套数组的指定节点直接子项

树形结构节点查询实现方案(JS/TS)

原始数据

const data = [
  {
    name: "Car",
    id: "19",
    count: "20",
    depth: "1",
    children: [
      {
        name: "Wheel",
        id: "22",
        count: "3",
        depth: "2",
        children: [
          {
            name: "Engine",
            id: "101",
            count: "1",
            depth: "3",
            children: [
              {
                name: "Engine and Brakes",
                id: "344",
                count: "1",
                depth: "4",
                children: []
              }
            ]
          }
        ]
      }
    ]
  },
  {
    name: "Bike",
    id: "3",
    count: "12",
    depth: "1",
    children: [
      {
        name: "SpeedBike",
        id: "4",
        count: "12",
        depth: "2",
        children: []
      }
    ]
  }
];

需求说明

  • 传入多个分类ID(如['101', '3'])时,返回对应节点的直接子项,仅保留name、id、count字段
  • 未传入ID时,默认返回所有一级节点及其直接子项,同样保留指定字段
  • 若传入的ID无直接子项则返回空数组
  • 禁止使用for、forEach、while循环,支持任意深度的层级结构

JS实现方案

// 递归查找目标ID节点的直接子项
const findNodeById = (nodes, targetIds) => {
  return nodes.flatMap(node => {
    // 当前节点匹配目标ID则取出其子项,否则取空数组
    const matches = targetIds.includes(node.id) ? node.children : [];
    // 递归处理子节点,确保深层级ID被匹配
    const childMatches = findNodeById(node.children, targetIds);
    return [...matches, ...childMatches];
  });
};

// 格式化节点,只保留需要的字段
const formatNode = node => ({ name: node.name, id: node.id, count: node.count });

// 主查询函数
const getTargetChildren = (sourceData, targetIds = null) => {
  if (!targetIds) {
    // 未传ID时,返回所有一级节点+它们的直接子项
    return sourceData.flatMap(node => [
      formatNode(node),
      ...node.children.map(formatNode)
    ]);
  }
  
  // 传ID时,获取匹配节点的直接子项并格式化
  const matchedChildren = findNodeById(sourceData, targetIds);
  return matchedChildren.map(formatNode);
};

测试用例

  1. 传入ID列表['101', '3']:
console.log(getTargetChildren(data, ['101', '3']));
// 输出:
// [
//   { name: "Engine and Brakes", id: "344", count: "1" },
//   { name: "SpeedBike", id: "4", count: "12" }
// ]
  1. 未传入ID:
console.log(getTargetChildren(data));
// 输出:
// [
//   { name: "Car", id: "19", count: "20" },
//   { name: "Wheel", id: "22", count: "3" },
//   { name: "Bike", id: "3", count: "12" },
//   { name: "SpeedBike", id: "4", count: "12" }
// ]
  1. 传入无子女的ID(如['344']):
console.log(getTargetChildren(data, ['344']));
// 输出:[]

TS实现方案

// 定义节点类型
interface TreeNode {
  name: string;
  id: string;
  count: string;
  depth: string;
  children: TreeNode[];
}

// 定义格式化后的节点类型
interface FormattedNode {
  name: string;
  id: string;
  count: string;
}

// 原始数据(带类型标注)
const data: TreeNode[] = [
  {
    name: "Car",
    id: "19",
    count: "20",
    depth: "1",
    children: [
      {
        name: "Wheel",
        id: "22",
        count: "3",
        depth: "2",
        children: [
          {
            name: "Engine",
            id: "101",
            count: "1",
            depth: "3",
            children: [
              {
                name: "Engine and Brakes",
                id: "344",
                count: "1",
                depth: "4",
                children: []
              }
            ]
          }
        ]
      }
    ]
  },
  {
    name: "Bike",
    id: "3",
    count: "12",
    depth: "1",
    children: [
      {
        name: "SpeedBike",
        id: "4",
        count: "12",
        depth: "2",
        children: []
      }
    ]
  }
];

// 递归查找目标ID节点的直接子项
const findNodeById = (nodes: TreeNode[], targetIds: string[]): TreeNode[] => {
  return nodes.flatMap(node => {
    const matches = targetIds.includes(node.id) ? node.children : [];
    const childMatches = findNodeById(node.children, targetIds);
    return [...matches, ...childMatches];
  });
};

// 格式化节点
const formatNode = (node: TreeNode): FormattedNode => ({
  name: node.name,
  id: node.id,
  count: node.count
});

// 主查询函数
const getTargetChildren = (sourceData: TreeNode[], targetIds?: string[]): FormattedNode[] => {
  if (targetIds === undefined) {
    return sourceData.flatMap(node => [
      formatNode(node),
      ...node.children.map(formatNode)
    ]);
  }
  
  const matchedChildren = findNodeById(sourceData, targetIds);
  return matchedChildren.map(formatNode);
};

实现逻辑说明

  • findNodeById:通过flatMap递归遍历所有节点,匹配到目标ID时取出其直接子项,同时递归处理子节点,确保深层级ID也能被找到
  • formatNode:统一处理节点字段,过滤掉不需要的属性
  • getTargetChildren:分场景处理请求:
    • 未传ID时,用flatMap将一级节点和其子项合并为一个数组后格式化
    • 传ID时,调用递归函数获取所有匹配子项,再格式化返回
  • 全程使用flatMap、map、includes等方法替代传统循环,满足要求

内容的提问来源于stack exchange,提问作者CEJ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 15:55:11