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

JavaScript ES6如何遍历嵌套层级不一致的combinedPorts数组

问题描述

我有如下结构的数组,其中包含键名为combinedPorts的嵌套数组。当所有对象的combinedPorts嵌套层级一致时,我可以直接用ES6的.map方法遍历并展示对应属性;但在示例数据中,第一个对象的combinedPorts键共嵌套3层,第二个对象的combinedPorts键仅嵌套2层。请问当不同对象的combinedPorts嵌套深度存在差异时,应当如何遍历该键对应的内容?

示例数据如下:

[
    {
        "name": "Test Source",
        "combinedPorts": [
            {
                "name": "PortGroup_1",
                "templateId": "edfb5b72ec580b129465ea0e8029bad3",
                "type": "SourcePorts",
                "combinedPorts": [
                    {
                        "name": "Source_1",
                        "templateId": "2355fc02e18cd48c6b487aa8b6f75959",
                        "type": "SourcePorts",
                        
                        "combinedPorts": [
                            {
                                "name": "Sami_TestSource",
                                "templateId": "0007ad49ea9b02b309a1248592a01981",
                                "type": "SourcePorts"
                            },
                            
                        ],
                        
                    }
                ],
                
            }
        ],
        "portGroupInfo": []
    },
    {
        "name": "Test Source",
        "combinedPorts": [
            {
                "name": "PortGroup_1",
                "templateId": "edfb5b72ec580b129465ea0e8029bad3",
                "type": "SourcePorts",
                "combinedPorts": [
                    {
                        "name": "Source_1",
                        "templateId": "2355fc02e18cd48c6b487aa8b6f75959",
                        "type": "SourcePorts"
                    }
                ],
                
            }
        ],
        "portGroupInfo": []
    }
]
解决方案

处理这种层级不固定的嵌套结构,别硬写固定层数的.map,写个递归遍历函数就行,逻辑非常简单:只要当前节点存在非空的combinedPorts数组,就继续往下遍历,直到节点没有下一层combinedPorts就停止,天然适配不同对象的嵌套深度差,不需要提前知道每个对象嵌了多少层。

基础遍历实现

这个版本可以遍历到每一层的所有节点,你可以在回调里写自己的渲染、数据处理逻辑:

/**
 * 递归遍历combinedPorts节点
 * @param {Array} nodes 待遍历的节点数组
 * @param {number} level 当前遍历层级,从0开始
 * @param {Function} callback 每个节点的处理函数,接收当前节点和层级作为参数
 */
function traverseCombinedPorts(nodes, level = 0, callback) {
  nodes.forEach(node => {
    // 先处理当前节点,不管它有没有子节点
    callback(node, level);
    // 存在非空子节点数组就递归进下一层
    if (Array.isArray(node.combinedPorts) && node.combinedPorts.length) {
      traverseCombinedPorts(node.combinedPorts, level + 1, callback);
    }
  });
}

// 调用示例
const yourData = []; // 替换成你自己的原始数组
yourData.forEach(topItem => {
  if (Array.isArray(topItem.combinedPorts)) {
    traverseCombinedPorts(topItem.combinedPorts, 0, (port, level) => {
      // 这里写你的业务逻辑,比如渲染列表、打印信息
      console.log(`第${level}层端口:`, port.name, port.type);
    });
  }
});

只取最底层叶子节点

如果你不需要中间的分组节点,只想拿到最内层没有子combinedPorts的实际端口,可以用这个版本,直接返回所有叶子节点的扁平数组:

function getLeafPortList(nodes, res = []) {
  nodes.forEach(node => {
    const hasChild = Array.isArray(node.combinedPorts) && node.combinedPorts.length;
    if (hasChild) {
      getLeafPortList(node.combinedPorts, res);
    } else {
      res.push(node);
    }
  });
  return res;
}

// 调用示例
const allLeafPorts = [];
yourData.forEach(topItem => {
  if (Array.isArray(topItem.combinedPorts)) {
    allLeafPorts.push(...getLeafPortList(topItem.combinedPorts));
  }
});

补充:如果你的数据有可能出现循环引用(极端场景下子节点指回上层节点),可以加一个Set存已经遍历过的节点id,避免死循环,常规业务端口数据一般不会有这种问题,按需添加即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 01:01:14