js 将线性数据转为树形的示例代码


Posted in Javascript onMay 28, 2019

在日常开发工作中,我们经常碰到将线性的数据转换成树的需求,今天给大家分享一个简单的转换算法。

数据结构

下面是我们转换前的数据:

[
  {
    "id":1,
    "parent_id":0,
    "name":"四川省"
  },
  {
    "id":2,
    "parent_id":0,
    "name":"广东省"
  },
  {
    "id":3,
    "parent_id":0,
    "name":"江西省"
  },
  {
    "id":5,
    "parent_id":1,
    "name":"成都市"
  },
  {
    "id":6,
    "parent_id":5,
    "name":"锦江区"
  },
  {
    "id":7,
    "parent_id":6,
    "name":"九眼桥"
  },
  {
    "id":8,
    "parent_id":6,
    "name":"兰桂坊"
  },
  {
    "id":9,
    "parent_id":2,
    "name":"东莞市"
  },
  {
    "id":10,
    "parent_id":9,
    "name":"长安镇"
  },
  {
    "id":11,
    "parent_id":3,
    "name":"南昌市"
  }
]

我们转换后的结果是:

[
  {
    "id":1,
    "parent_id":0,
    "name":"四川省",
    "children":[
      {
        "id":5,
        "parent_id":1,
        "name":"成都市",
        "children":[
          {
            "id":6,
            "parent_id":5,
            "name":"锦江区",
            "children":[
              {
                "id":7,
                "parent_id":6,
                "name":"九眼桥"
              },
              {
                "id":8,
                "parent_id":6,
                "name":"兰桂坊"
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "id":2,
    "parent_id":0,
    "name":"广东省",
    "children":[
      {
        "id":9,
        "parent_id":2,
        "name":"东莞市",
        "children":[
          {
            "id":10,
            "parent_id":9,
            "name":"长安镇"
          }
        ]
      }
    ]
  },
  {
    "id":3,
    "parent_id":0,
    "name":"江西省",
    "children":[
      {
        "id":11,
        "parent_id":3,
        "name":"南昌市"
      }
    ]
  }
]

实现代码

let array = [
  {
    id: 1,
    parent_id: 0,
    name: "四川省"
  },
  {
    id: 2,
    parent_id: 0,
    name: "广东省"
  },
  {
    id: 3,
    parent_id: 0,
    name: "江西省"
  },
  {
    id: 5,
    parent_id: 1,
    name: "成都市"
  },
  {
    id: 6,
    parent_id: 5,
    name: "锦江区"
  },
  {
    id: 7,
    parent_id: 6,
    name: "九眼桥"
  },
  {
    id: 8,
    parent_id: 6,
    name: "兰桂坊"
  },
  {
    id: 9,
    parent_id: 2,
    name: "东莞市"
  },
  {
    id: 10,
    parent_id: 9,
    name: "长安镇"
  },
  {
    id: 11,
    parent_id: 3,
    name: "南昌市"
  }
]

function listToTree(list) {
  let map = {};
  list.forEach(item => {
    if (! map[item.id]) {
      map[item.id] = item;
    }
  });

  list.forEach(item => {
    if (item.parent_id !== 0) {
      map[item.parent_id].children ? map[item.parent_id].children.push(item) : map[item.parent_id].children = [item];
    }
  });
  
  return list.filter(item => {
    if (item.parent_id === 0) {
      return item;
    }
  })
}
console.log(listToTree(array));

分析

这段代码的核心就在 listToTree 方法中,这个方法分为了三个部分:

第一部分

第一部分先将数组中的所有元素都复制到 map 中(注意:这里是引用复制哦,这个细节很重要)。

第二部分

执行第二次遍历前的 map:

// map
{
 ...,
 "3":{
    "id":3,
    "parent_id":0,
    "name":"江西省"
  },
  ...
}

然后这个时候遍历 parent_id 不等于 0 的元素:

[
 ...,
 {
 id: 11,
 parent_id: 3,
 name: "南昌市"
 },
  ...
]

然后发现南昌市有 parent_id,我们再给 map[item.parent_id] 设置子元素,通过南昌市的 parent_id 可以推导出:

map["3"].children ? map["3"].children.push(item) : map[3].children = [item];

上面的代码判断了是否存在 children,如果不存在则直接给它赋值,否则将值 push 到 children 中。

执行完第二步后,我们已经把子节点添加到了它的父节点上,但是我们并没有删除掉之前的子节点。所以第三部就是对数据进行过滤,只要父节点即可。

js 将线性数据转为树形的示例代码

总结

需要注意的是,我们一直都是对 map 进行操作的,但是结果怎么到了 list 上呢,这就是上面提到的引用复制。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery之排序组件的深入解析
Jun 19 Javascript
Jquery 复选框取值兼容FF和IE8(测试有效)
Oct 29 Javascript
jquery和ajax的关系详细介绍
Nov 29 Javascript
js动态添加表格数据使用insertRow和insertCell实现
May 22 Javascript
Jquery 获取指定标签的对象及属性的设置与移除
May 29 Javascript
Firefox下无法正常显示年份的解决方法
Sep 04 Javascript
jQuery中delegate()方法用法实例
Jan 19 Javascript
js实现简单锁屏功能实例
May 27 Javascript
详解为Angular.js内置$http服务添加拦截器的方法
Dec 20 Javascript
Vue实现动态响应数据变化
Apr 28 Javascript
vue组件实现弹出框点击显示隐藏效果
Oct 26 Javascript
JavaScript实现简单动态表格
Dec 02 Javascript
React中使用外部样式的3种方式(小结)
May 28 #Javascript
vue实现多条件和模糊搜索功能
May 28 #Javascript
vue实现路由切换改变title功能
May 28 #Javascript
Vue 无限滚动加载指令实现方法
May 28 #Javascript
vue实现搜索过滤效果
May 28 #Javascript
微信小程序 image组件遇到的问题
May 28 #Javascript
vue实现搜索功能
May 28 #Javascript
You might like
PHP+DBM的同学录程序(1)
2006/10/09 PHP
PHP面向对象的使用教程 简单数据库连接
2006/11/25 PHP
基于php设计模式中工厂模式详细介绍
2013/05/15 PHP
twig里使用js变量的方法
2016/02/05 PHP
php添加数据到xml文件的简单例子
2016/09/08 PHP
PHP实现在windows下配置sendmail并通过mail()函数发送邮件的方法
2017/06/20 PHP
js实现网站首页图片滚动显示
2013/02/04 Javascript
from表单多个按钮提交用onclick跳转不同action
2014/04/24 Javascript
javascript入门教程基础篇
2015/11/16 Javascript
bootstrap-treeview自定义双击事件实现方法
2016/01/09 Javascript
前端面试题及答案整理(二)
2016/08/26 Javascript
AngularJS修改model值时,显示内容不变的实例
2018/09/13 Javascript
详解webpack4.x之搭建前端开发环境
2019/03/28 Javascript
Vue打包后访问静态资源路径问题
2019/11/08 Javascript
javascript前端实现多视频上传
2020/12/13 Javascript
[01:51]历届DOTA2国际邀请赛举办地回顾 TI9落地上海
2018/08/26 DOTA
[46:55]LGD vs Liquid 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/19 DOTA
二种python发送邮件实例讲解(python发邮件附件可以使用email模块实现)
2013/12/03 Python
python根据开头和结尾字符串获取中间字符串的方法
2015/03/26 Python
在Python程序和Flask框架中使用SQLAlchemy的教程
2016/06/06 Python
使用python调用zxing库生成二维码图片详解
2017/01/10 Python
Python IDLE 错误:IDLE''s subprocess didn''t make connection 的解决方案
2017/02/13 Python
django缓存配置的几种方法详解
2018/07/16 Python
python取数作为临时极大值(极小值)的方法
2018/10/15 Python
python读取tif图片时保留其16bit的编码格式实例
2020/01/13 Python
Pytest mark使用实例及原理解析
2020/02/22 Python
python GUI编程(Tkinter) 创建子窗口及在窗口上用图片绘图实例
2020/03/04 Python
在python中使用pyspark读写Hive数据操作
2020/06/06 Python
matplotlib 画双轴子图无法显示x轴的解决方法
2020/07/27 Python
爱耳日活动总结
2014/04/30 职场文书
社区志愿者活动总结
2014/06/26 职场文书
单位消防安全责任书
2014/07/23 职场文书
2015年电厂工作总结范文
2015/05/13 职场文书
golang 实现Location跳转方式
2021/05/02 Golang
swagger如何返回map字段注释
2021/07/03 Java/Android
详解 TypeScript 枚举类型
2021/11/02 Javascript