js将列表组装成树结构的两种实现方式分享

 更新时间:2022年01月09日 11:29:41   作者:Orime小猪  
最近做的任务提了新的需求,需要实现一个树形结构,所以下面这篇文章主要给大家介绍了关于js将列表组装成树结构的两种实现方式,需要的朋友可以参考下

前言

工作中偶尔就会遇到后端同学丢来一个列表,要我们自己组装成一个树结构渲染到页面上,本文以两种不同方式探索生成树的算法思想。

image.png

背景介绍

可组装成树结构的数组一般有以下几个要素:

  • 当前节点id
  • parentId 当前节点的父节点id
  • children 子节点列表(可能不会在接口中返回,需要组装时候自己加上)

原始结构:

目标结构:

关键就是一维数组中通过parentId找到其对应的父节点并添加到父节点的children数组中。

实现方案

最直接的方式就是遍历数组,并把找到的子节点逐一添加到父节点中

function listToTreeSimple(data) {
  const res = [];
  data.forEach((item) => {
    const parent = data.find((node) => node.id === item.parentId);
    if (parent) {
      parent.children = parent.children || [];
      parent.children.push(item);
    } else {
      // * 根节点
      res.push(item);
    }
  });
  return res;
}

考虑进一步优化,使用哈希表,以id为key存储每个节点值,省去data.find计算

function listToTree(data) {
  // * 先生成parent建立父子关系
  const obj = {};
  data.forEach((item) => {
    obj[item.id] = item;
  });
  // * obj -> {1001: {id: 1001, parentId: 0, name: 'AA'}, 1002: {...}}
  // console.log(obj, "obj")
  const parentList = [];
  data.forEach((item) => {
    const parent = obj[item.parentId];
    if (parent) {
      // * 当前项有父节点
      parent.children = parent.children || [];
      parent.children.push(item);
    } else {
      // * 当前项没有父节点 -> 顶层
      parentList.push(item);
    }
  });
  return parentList;
}

即便数据量很小,带来的性能提升也是显著的

递归法

更有骚操作递归法,性能会很差,但代码会很酷😎

function recursiveToTree(data) {
  function loop(key) {
    const arr = [];
    data.forEach((item) => {
      if (item.parentId === key) {
        item.children = loop(item.id);
        arr.push(item);
      }
    });
    return res;
  }
  return loop(1);
}

看看性能,诶?看起来竟然递归性能最佳🤔

但是数据量稍微大一点……

(上面递归,下面非递归)

资源

原始数据列表

const list = [
  {
    id: 1001,
    parentId: 0,
    name: "AA",
  },
  {
    id: 1002,
    parentId: 1001,
    name: "BB",
  },
  {
    id: 1003,
    parentId: 1001,
    name: "CC",
  },
  {
    id: 1004,
    parentId: 1003,
    name: "DD",
  },
  {
    id: 1005,
    parentId: 1003,
    name: "EE",
  },
  {
    id: 1006,
    parentId: 1002,
    name: "FF",
  },
  {
    id: 1007,
    parentId: 1002,
    name: "GG",
  },
  {
    id: 1008,
    parentId: 1004,
    name: "HH",
  },
  {
    id: 1009,
    parentId: 1005,
    name: "II",
  },
];

总结

到此这篇关于js将列表组装成树结构的两种实现方式的文章就介绍到这了,更多相关js列表组装成树结构内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • js HTML5 Ajax实现文件上传进度条功能

    js HTML5 Ajax实现文件上传进度条功能

    这篇文章主要介绍了javascript实现文件上传进度条功能的相关资料啊,感兴趣的朋友可以参考一下
    2016-02-02
  • 浅谈PDF.js使用心得

    浅谈PDF.js使用心得

    本篇文章主要介绍了浅谈PDF.js使用心得,pdf.js 是一个技术原型主要用于在 HTML5 平台上展示 PDF 文档,无需任何本地技术支持。非常具有实用价值,需要的朋友可以参考下
    2018-06-06
  • JS实现自动阅读单词(有道单词本添加功能)

    JS实现自动阅读单词(有道单词本添加功能)

    有道单词客户Duan没有自动阅读的功能, 本文用强大的js实现了简单的自动下一个单词的功能,需要的朋友可以参考下
    2016-11-11
  • 微信小程序使用npm支持踩坑

    微信小程序使用npm支持踩坑

    这篇文章主要介绍了微信小程序使用npm支持踩坑,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-11-11
  • 微信小程序使用swiper组件实现类3D轮播图

    微信小程序使用swiper组件实现类3D轮播图

    在写微信小程序时,有写到实现3D轮播图的效果,可以直接使用微信小程序中自带的组件swiper来实现。下面通过实例代码给大家介绍微信小程序轮播图的实现方法,感兴趣的朋友一起看看吧
    2018-08-08
  • JavaScript利用正则表达式替换字符串中的内容

    JavaScript利用正则表达式替换字符串中的内容

    本文主要介绍了JavaScript利用正则表达式替换字符串中内容的具体实现方法,并做了简要注释,便于理解。具有一定的参考价值,需要的朋友可以看下
    2016-12-12
  • js常用函数2008-8-16整理

    js常用函数2008-8-16整理

    方便使用js的朋友,把下面的函数找到你想要的功能函数,复制部分判断输入文本是否为身份证号码,如为不正确则提示
    2008-08-08
  • 解决input输入框仅支持输入数字及两位小数点的限制

    解决input输入框仅支持输入数字及两位小数点的限制

    这篇文章主要为大家介绍了解决input输入框仅支持输入数字及两位小数点的限制技巧示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • bootstrap选项卡使用方法解析

    bootstrap选项卡使用方法解析

    这篇文章主要为大家详细介绍了bootstrap选项卡使用方法,包括选项卡组件和底部可以切换的选项卡面板使用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01
  • JS模拟的Map类实现方法

    JS模拟的Map类实现方法

    这篇文章主要介绍了JS模拟的Map类实现方法,可实现模拟java中map属性按照键值对保存的功能,提供了采用数组和json两种实现方式,需要的朋友可以参考下
    2016-06-06

最新评论