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

目录
  • 前言
  • 背景介绍
  • 实现方案
  • 递归法
  • 资源
  • 总结

前言

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

背景介绍

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

  • 当前节点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;
}

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

递归法

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

时间: 2022-01-08

JavaScript解析任意形式的json树型结构展示

在页面展示json成树形结构时,往往得到的json不是ztree的规范格式,需要对json循环迭代解析.即使不规范的json也可以树形展现: var arrayJsonContent=[]; //节点类 var JsonNodes = { id:"", name:"", pId:"", content:"", //location:"", linklocation:"", open:fa

js用于树型结构级联选择

及联选择-用于权限选择比较合适 var arr = tree.getElementsByTagName('input') for(var i=0; i [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]

javascript如何用递归写一个简单的树形结构示例

现在有一个数据,需要你渲染出对应的列表出来: var data = [ {"id":1}, {"id":2}, {"id":3}, {"id":4}, ]; var str="<ul>"; data.forEach(function(v,i){ str+="<li><span>"+v.id+"</span></li>&

JavaScript几种形式的树结构菜单

1.悬浮层树(Tree) 这种树结构实现类似面包屑导航功能,监听的是节点鼠标移动的事件,然后在节点下方或右方显示子节点,依此递归显示子节点的子节点. 用户首页博客设置文章相册留言评论系统 这里要注意几个小问题,其一这种树结构是悬浮层绝对定位的,在创建层的时候一定要直接放在body的下面,这样做的是确保在IE里面能遮掩住任何层,因为在IE里面是有stacking context这种东西的潜规则在里面的,另外当然还有一个select你能遮住我吗?老掉牙的问题,这里是采用在每个悬浮层后面加个ifram

JavaScript 处理树数据结构的方法示例

JavaScript 处理树结构数据 场景 即便在前端,也有很多时候需要操作 树结构 的情况,最典型的场景莫过于 无限级分类.之前吾辈曾经遇到过这种场景,但当时没有多想直接手撕 JavaScript 列表转树了,并没有想到进行封装.后来遇到的场景多了,想到如何封装树结构操作,但考虑到不同场景的树节点结构的不同,就没有继续进行下去了. 直到吾辈开始经常运用了 ES6 Proxy 之后,吾辈想到了新的解决方案! 思考 问: 之前为什么停止封装树结构操作了? 答: 因为不同的树结构节点可能有不同的结构

javascript将list转换成树状结构的实例

如下所示: /** * 将list装换成tree * @param {Object} myId 数据主键id * @param {Object} pId 数据关联的父级id * @param {Object} list list集合 */ function listToTree(myId,pId,list){ function exists(list, parentId){ for(var i=0; i<list.length; i++){ if (list[i][myId] == parent

详解JavaScript树结构

对于数据结构"树",想必大家都熟悉,今儿,我们就再来回顾一下数据结构中的二叉树与树,并用JavaScript实现它们. ps:树结构在前端中,很多地方体现得淋漓尽致,如Vue的虚拟DOM以及冒泡等等. 二叉树 --概念-- 二叉树是一种树形结构,它的特点是每个结点至多只有两棵子树(即二叉树中不存在度大于2的结点),并且,二叉树的子树有左右之分,其次序不能任意颠倒. 如下,就是一棵二叉树(注:下文二叉树相关例子,都以该二叉树为例): 且,遍历二叉树(traversing binary t

详解JavaScript基于面向对象之创建对象(2)

接着上文<详解JavaScript基于面向对象之创建对象(1)>继续学习. 4.原型方式        我们创建的每个函数都有一个通过prototype(原型)属性,这个属性是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法.逻辑上可以这么理解:prototypt通过条用构造函数而创建的那个对象的原型对象.使用原型的好处就是可以让所有对象实例共享它所包含的属性和方法.也就是说,不必在构造函数中定义对象信息,而是直接将这些信息添加到原型中.        原型方式利用了对象的pr

详解JavaScript基于面向对象之继承实例

javascript面向对象继承的简单实例: 作为一门面向对象的语言,继承自然是它的一大特性,尽管javascript的面向对象的实现机制和和c#和java这样典型的面向对象不同,但是继承的基本特点还是具有的,简单的说就是获得父级的方法和属性,下面是一段简单的实例,大家有兴趣可以分析一下: window.onload = function(){ function parent(age,name){ this.age = age; this.name = name; } parent.protot

详解JavaScript基于面向对象之继承

一.面相对象继承机制       这个实例使用UML很好的解释了继承机制.       说明继承机制最简单的方式是,利用一个经典的例子就是几何形状.实际上,几何形状只有两种,即椭圆形(是圆形的)和多边形(具有一定数量的边).圆是椭圆的一种,它只有一个焦点.三角形.矩形和五边形都是多边形的一种,具有不同数量的边.正方形是矩形的一种,所有的边等长.这就构成了一种完美的继承关系,很好的解释了面向对象的继承机制.        在这个例子中,形状是椭圆形和多边形的基类(通常我们也可以叫它父类,所有类都由

详解JavaScript中的4种类型识别方法

具体内容如下: 1.typeof [输出]首字母小写的字符串形式 [功能] [a]可以识别标准类型(将Null识别为object) [b]不能识别具体的对象类型(Function除外) [实例] console.log(typeof "jerry");//"string" console.log(typeof 12);//"number" console.log(typeof true);//"boolean" console

详解javascript实现瀑布流绝对式布局

瀑布流也应该算是流行几年了吧.首先是由Pinterest掀起的浪潮,然后国内设计如雨后春笋般,冒出很多瀑布流的例子,比如,蘑菇街,Mark之(不过最近涉黄,好像被喝茶了),还有淘宝的 "哇哦". 这些都是很棒的例子, 今天我们就聊一聊瀑布流. 一.绝对式布局: JS实现原理 其实瀑布式主要的难点就在于,如果将图片整齐的排列在对应的列下,以及什么时候开始刷新加载图片. 而图片整齐的排列的主要逻辑和算法即,先获取容器内可以放多少列,然后,通过计算,存放第一列的高度,再遍历剩下(除第一列的元

详解JavaScript 中getElementsByName在IE中的注意事项

详解JavaScript 中getElementsByName在IE中的注意事项 前言: 在IE5-9中是没有实现js的 getElementsByClassName()方法,但是实现了getElementsByName()方法,但是需要注意的是这个方法在IE5-9中也返回id属性匹配的指定元素,为了兼容,应该小心谨慎使用,不要将同样的字符串同时用作了名字和ID. 测试程序如下: <div id="log"> <div id="innerLog"&

详解Javascript中prototype属性(推荐)

在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不存在类(Class)的概念的,javascript中不是基于'类的',而是通过构造函数(constructor)和原型链(prototype chains)实现的.但是在ES6中提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板.通过class关键字,可以定义类.基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能

详解JavaScript基本类型和引用类型

一.值的类型        早在介绍JS的数据类型的时候就提到过基本类型和引用类型,不过在说两种类型之前,我们先来了解一下变量的值的类型.在ECMAScript中,变量可以存在两种类型的值,即原始值和引用值. (1)原始值        存储在栈中的简单数据段,也就是说,它们的值直接存储在变量访问的位置. (2)引用值        存储在堆中的对象,也就是说,存储在变量处的值是一个指针,指向存储对象的内存处.        为变量赋值时,ECMAScript的解释程序必须判断该值是原始类型,还

js对象实例详解(JavaScript对象深度剖析,深度理解js对象)

这算是酝酿很久的一篇文章了. JavaScript作为一个基于对象(没有类的概念)的语言,从入门到精通到放弃一直会被对象这个问题围绕. 平时发的文章基本都是开发中遇到的问题和对最佳解决方案的探讨,终于忍不住要写一篇基础概念类的文章了. 本文探讨以下问题,在座的朋友各取所需,欢迎批评指正: 1.创建对象 2.__proto__与prototype 3.继承与原型链 4.对象的深度克隆 5.一些Object的方法与需要注意的点 6.ES6新增特性 下面反复提到实例对象和原型对象,通过构造函数 new