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 相关文章推荐
js 编码转换 gb2312 和 utf8 互转的2种方法
Aug 07 Javascript
js和jquery中循环的退出和继续下一个循环
Sep 03 Javascript
使用JavaScript实现旋转的彩圈特效
Jun 23 Javascript
PageSwitch插件实现100种不同图片切换效果
Jul 28 Javascript
jquery中的工具使用方法$.isFunction, $.isArray(), $.isWindow()
Aug 09 Javascript
jquery中实现时间戳与日期相互转换
Apr 12 Javascript
AngularJs基于角色的前端访问控制的实现
Nov 07 Javascript
jQuery插件FusionCharts实现的Marimekko图效果示例【附demo源码】
Mar 24 jQuery
vue2.0父子组件间通信的实现方法
Apr 19 Javascript
js中字符型和数值型数字的互相转化方法(必看)
Apr 25 Javascript
babel7.x和webpack4.x配置vue项目的方法步骤
May 12 Javascript
jquery插件实现轮播图效果
Oct 19 jQuery
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生成带有雪花背景的验证码
2006/10/09 PHP
php5.2.0内存管理改进
2007/01/22 PHP
php无限分类且支持输出树状图的详细介绍
2013/06/19 PHP
php格式化时间戳
2016/12/17 PHP
PHP二维数组去重算法
2016/12/17 PHP
jQuery 获取对象 基本选择与层级
2010/05/31 Javascript
Javascript面向对象编程(三) 非构造函数的继承
2011/08/28 Javascript
window.onload与$(document).ready()的区别分析
2015/05/30 Javascript
JavaScript中的this陷阱的最全收集并整理(没有之一)
2017/02/21 Javascript
使用javaScript实现鼠标拖拽事件
2020/04/03 Javascript
redux中间件之redux-thunk的具体使用
2018/04/17 Javascript
vue 修改 data 数据问题并实时显示的方法
2018/08/27 Javascript
Vue render函数实战之实现tabs选项卡组件
2019/04/22 Javascript
js实现淘宝首页的banner栏效果
2019/11/26 Javascript
JavaScript实现多球运动效果
2020/09/07 Javascript
跟老齐学Python之有容乃大的list(1)
2014/09/14 Python
Python文本处理之按行处理大文件的方法
2018/04/09 Python
Django重装mysql后启动报错:No module named ‘MySQLdb’的解决方法
2018/04/22 Python
手把手教你如何安装Pycharm(详细图文教程)
2018/11/28 Python
详解pandas的外部数据导入与常用方法
2019/05/01 Python
python用match()函数爬数据方法详解
2019/07/23 Python
Python如何使用ElementTree解析xml
2020/10/12 Python
利用CSS3的checked伪类实现OL的隐藏显示的方法
2010/12/18 HTML / CSS
乌克兰的第一家手表店:Deka
2020/03/05 全球购物
会展策划与管理专业大学生职业生涯规划
2014/02/07 职场文书
自荐信的格式
2014/03/10 职场文书
投资意向书
2014/07/30 职场文书
解放思想演讲稿
2014/09/11 职场文书
甜品店创业计划书
2014/09/21 职场文书
成本会计实训报告
2014/11/05 职场文书
2014年小学德育工作总结
2014/12/05 职场文书
房地产项目合作意向书
2015/05/08 职场文书
预备党员入党思想汇报(范文)
2019/08/14 职场文书
使用Python脚本对GiteePages进行一键部署的使用说明
2021/05/27 Python
MySQL into_Mysql中replace与replace into用法案例详解
2021/09/14 MySQL
mysql 生成连续日期及变量赋值
2022/03/20 MySQL