数组转Tree

74 阅读4分钟
let data = [
  {
    "id": 1,
    "project": "项目1",
    "operation": "运营商1",
    "version": "版本1",
    "name": "名称1",
    "age": "23",
    "address": "地址1"
  },
  {
    "id": 2,
    "project": "项目2",
    "operation": "运营商1",
    "version": "版本1",
    "name": "名称1",
    "age": "23",
    "address": "地址1"
  },
  {
    "id": 3,
    "project": "项目1",
    "operation": "运营商2",
    "version": "版本1",
    "name": "名称1",
    "age": "23",
    "address": "地址1"
  },
  {
    "id": 4,
    "project": "项目2",
    "operation": "运营商1",
    "version": "版本1",
    "name": "名称1",
    "age": "23",
    "address": "地址1"
  },
  {
    "id": 5,
    "project": "项目1",
    "operation": "运营商2",
    "version": "版本2",
    "name": "名称1",
    "age": "23",
    "address": "地址1"
  }
]
const indexArray = ["project", "version", "operation"];

/**
 * 第一个函数的思路是逐个遍历原始数据数组中的每个项,并根据索引层级数组构建树状结构。它通过嵌套的循环来逐层创建节点,并将数据项插入到正确的节点中。

具体思路如下:

初始化根节点数组 root,用于存储最终的树状结构。
对于数据数组中的每个项 item,从根节点数组开始构建层级。
针对每个索引层级,依次进行处理:
  获取当前索引对应的值 value,即 item[index]。
  在当前层级 currentLevel 中查找具有相同标签 value 的子节点 child。
  如果找不到子节点,创建一个新的子节点 child,并将其加入到当前层级 currentLevel 中。
  将 currentLevel 更新为新的子节点的子节点数组,即 currentLevel = child.children。
在最后一层节点的子节点数组中,将当前项 item 直接插入。
循环结束后,返回根节点数组 root,即构建好的树状结构。

这个函数的主要思路是通过循环和条件判断逐层构建树的结构,但它没有使用更高级的数据结构或算法来优化查找操作的效率,因此时间复杂度较高。

 */
function buildTree1(data, indexArray) {
  const root = [];
  
  for (const item of data) {
    let currentLevel = root;

    for (const index of indexArray) {
      const value = item[index];
      let child = currentLevel.find(node => node.label === value);

      if (!child) {
        child = { label: value, children: [] };
        currentLevel.push(child);
      }

      currentLevel = child.children;
    }

    currentLevel.push(item);
  }
  
  return root;
}



/**
 * 具体思路如下:

初始化根节点数组 root,用于存储最终的树状结构。
初始化空的哈希表 nodeMap,用于存储已经构建的节点。
对于数据数组中的每个项 item,从根节点数组开始构建层级。
针对每个索引层级,依次进行处理:
  获取当前索引对应的值 value,即 item[index]。
  根据索引和值生成唯一的节点标识 nodeId,例如使用 index + '_' + value。
  在哈希表 nodeMap 中查找具有标识 nodeId 的节点 child。
  如果找不到节点,说明该节点尚未构建,创建一个新的子节点 child,并将其加入到当前层级 currentLevel 和哈希表 nodeMap 中。
  将 currentLevel 更新为新的子节点的子节点数组,即 currentLevel = child.children。
在最后一层节点的子节点数组中,将当前项 item 直接插入。
循环结束后,返回根节点数组 root,即构建好的树状结构。
这个函数的主要思路是利用哈希表存储已经构建的节点,通过哈希表的快速查找能力,减少了查找操作的时间复杂度。这样可以在构建树的过程中快速定位已经存在的节点,避免重复创建,从而提高了整体的效率。


 */

function buildTree2(data, indexArray) {
  const root = [];
  const nodeMap = {}; // 哈希表用于存储已构建的节点
  
  for (const item of data) {
    let currentLevel = root;

    for (const index of indexArray) {
      const value = item[index];
      const nodeId = index + '_' + value;
      
      let child = nodeMap[nodeId];

      if (!child) {
        child = { label: value, children: [] };
        nodeMap[nodeId] = child;
        currentLevel.push(child);
      }

      currentLevel = child.children;
    }

    currentLevel.push(item);
  }
  
  return root;
}



const tree = buildTree(data, indexArray);
console.log(tree);

[
  {
    "label": "项目1",
    "children": [
      {
        "label": "版本1",
        "children": [
          {
            "label": "运营商1",
            "children": [
              {
                "id": 1,
                "project": "项目1",
                "operation": "运营商1",
                "version": "版本1",
                "name": "名称1",
                "age": "23",
                "address": "地址1"
              }
            ]
          },
          {
            "label": "运营商2",
            "children": [
              {
                "id": 3,
                "project": "项目1",
                "operation": "运营商2",
                "version": "版本1",
                "name": "名称1",
                "age": "23",
                "address": "地址1"
              }
            ]
          }
        ]
      },
      {
        "label": "版本2",
        "children": [
          {
            "label": "运营商2",
            "children": [
              {
                "id": 5,
                "project": "项目1",
                "operation": "运营商2",
                "version": "版本2",
                "name": "名称1",
                "age": "23",
                "address": "地址1"
              }
            ]
          }
        ]
      }
    ]
  },

  {
    "label": "项目2",
    "children": [
      {
        "label": "版本1",
        "children": [
          {
            "label": "运营商1",
            "children": [
              {
                "id": 2,
                "project": "项目2",
                "operation": "运营商1",
                "version": "版本1",
                "name": "名称1",
                "age": "23",
                "address": "地址1"
              },

              {
                "id": 4,
                "project": "项目2",
                "operation": "运营商1",
                "version": "版本1",
                "name": "名称1",
                "age": "23",
                "address": "地址1"
              }
            ]
          }
        ]
      }
    ]
  }
]