返回

数组转Tree别再“卷”了,直接上这几招就能秒杀面试官

前端




前言

最近在掘金上看到了不少关于扁平数组转树形结构的文章,都是各式各样,实际工作中,我也有过类似的场景,只不过更奇葩一点 ~

背景

我是做一个可视化开发平台,基于拖拉拽快速实现可视化页面(PC, 手机网页)。

我们的系统中,界面中的所有元素,比如按钮、文本框、图片等,都是以树形结构存储的,而前端工程师传入的数据,往往都是扁平的数组。

所以,在渲染界面之前,我们需要把这些扁平的数组转换成树形结构。

难点

由于历史原因,我们的前端工程师使用的是一种比较奇葩的数据结构,这种数据结构的特点是:

  • 每个节点都有一个唯一的id
  • 每个节点都有一个parent_id
  • 每个节点都有一个children属性,表示该节点的子节点

也就是说,我们的数据结构是这样的:

[
  {
    "id": 1,
    "parent_id": null,
    "children": [
      {
        "id": 2,
        "parent_id": 1,
        "children": []
      },
      {
        "id": 3,
        "parent_id": 1,
        "children": []
      }
    ]
  },
  {
    "id": 4,
    "parent_id": null,
    "children": [
      {
        "id": 5,
        "parent_id": 4,
        "children": []
      },
      {
        "id": 6,
        "parent_id": 4,
        "children": []
      }
    ]
  }
]

这种数据结构的特点是,每个节点都包含了其所有子节点的信息。

这样的数据结构,在某些场景下是很有用的,比如在做可视化的时候,我们可以直接把这个数据结构渲染成树形结构。

但是,在某些场景下,这种数据结构也是很麻烦的,比如在做数据统计的时候,我们需要把所有节点的数据都统计一遍,而这种数据结构,会导致我们重复统计很多次。

解决方案

为了解决这个问题,我们可以把这种奇葩的数据结构转换成一种更常见的树形结构。

树形结构的特点是:

  • 每个节点都有一个唯一的id
  • 每个节点都有一个parent_id
  • 每个节点都有一个children属性,表示该节点的子节点

也就是说,我们要把这种奇葩的数据结构转换成这样的数据结构:

{
  "id": 1,
  "parent_id": null,
  "children": [
    {
      "id": 2,
      "parent_id": 1,
      "children": []
    },
    {
      "id": 3,
      "parent_id": 1,
      "children": []
    }
  ]
}

这种数据结构的特点是,每个节点只包含了其直接子节点的信息。

这样的数据结构,在做数据统计的时候,可以大大减少重复统计的次数。

实现方案

要把奇葩的数据结构转换成树形结构,我们可以使用递归的方法。

递归的方法很简单,就是把问题分解成更小的子问题,然后逐个解决。

在我们的场景中,我们可以把问题分解成以下几个子问题:

  1. 找到根节点
  2. 把根节点的子节点转换成树形结构
  3. 把根节点的子节点的子节点转换成树形结构

以此类推,直到所有的节点都转换成树形结构。

function convert(data) {
  // 找到根节点
  const root = data.find(item => item.parent_id === null);

  // 把根节点的子节点转换成树形结构
  root.children = convertChildren(root.id, data);

  return root;
}

function convertChildren(parent_id, data) {
  // 找到该父节点的所有子节点
  const children = data.filter(item => item.parent_id === parent_id);

  // 把这些子节点转换成树形结构
  children.forEach(child => {
    child.children = convertChildren(child.id, data);
  });

  return children;
}

总结

以上就是把奇葩的数据结构转换成树形结构的解决方案。

这个解决方案很简单,但是很有效。

如果你也遇到了类似的问题,不妨试试这个解决方案。