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 相关文章推荐
Javascript之旅 对象的原型链之由来
Aug 25 Javascript
jquery固定底网站底部菜单效果
Aug 13 Javascript
基于JQuery实现的Select级联
Jan 27 Javascript
JavaScript获取按钮所在form表单id的方法
Apr 02 Javascript
jquery实现动态改变div宽度和高度
May 08 Javascript
JavaScript的面向对象编程基础
Aug 13 Javascript
javascript验证手机号和实现星号(*)代替实例
Aug 16 Javascript
Vue.js在使用中的一些注意知识点
Apr 29 Javascript
VsCode插件整理(小结)
Sep 14 Javascript
nuxt+axios解决前后端分离SSR的示例代码
Oct 24 Javascript
vue.draggable实现表格拖拽排序效果
Dec 01 Javascript
详解如何在vscode里面调试js和node.js的方法步骤
Dec 24 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根据用户名和手机号查询是否存在手机号码
2017/02/16 PHP
YII框架行为behaviors用法示例
2019/04/26 PHP
javascript 二维数组的实现与应用
2010/03/16 Javascript
基于jquery的地址栏射击游戏代码
2011/03/10 Javascript
jquery常用技巧及常用方法列表集合
2011/04/06 Javascript
用JQuery 判断某个属性是否存在hasAttr的解决方法
2013/04/26 Javascript
用js来获取上传的文件名纯粹是为了美化而用
2013/10/23 Javascript
在JavaScript的AngularJS库中进行单元测试的方法
2015/06/23 Javascript
跟我学习javascript的arguments对象
2015/11/16 Javascript
基于Nodejs利用socket.io实现多人聊天室
2017/02/22 NodeJs
详解webpack的配置文件entry与output
2017/08/21 Javascript
nodejs 最新版安装npm 的使用详解
2018/01/18 NodeJs
angular 内存溢出的问题解决
2018/07/12 Javascript
webpack4+Vue搭建自己的Vue-cli项目过程分享
2018/08/29 Javascript
vue使用rem实现 移动端屏幕适配
2018/09/26 Javascript
js+html实现点名系统功能
2019/11/05 Javascript
JavaScript利用键盘码控制div移动
2020/03/19 Javascript
Pthon批量处理将pdb文件生成dssp文件
2015/06/21 Python
python 将print输出的内容保存到txt文件中
2018/07/17 Python
python中import与from方法总结(推荐)
2019/03/21 Python
Python Opencv实现图像轮廓识别功能
2020/03/23 Python
基于pytorch的保存和加载模型参数的方法
2019/08/17 Python
Django Form设置文本框为readonly操作
2020/07/03 Python
python-地图可视化组件folium的操作
2020/12/14 Python
详解CSS3:overflow属性
2020/11/17 HTML / CSS
详解如何在登录过期后跳出Ifram框架
2020/09/10 HTML / CSS
EJB timer的种类
2014/10/28 面试题
实习生的自我评价
2014/01/08 职场文书
新闻发布会主持词
2014/03/28 职场文书
诉讼代理人授权委托书
2014/10/11 职场文书
2015元旦联欢晚会结束语
2014/12/14 职场文书
先进工作者个人总结
2015/02/15 职场文书
工作失职自我检讨书
2015/05/05 职场文书
导游词之太原天龙山
2020/01/02 职场文书
MySQL分库分表与分区的入门指南
2021/04/22 MySQL
mybatis中注解与xml配置的对应关系和对比分析
2021/08/04 Java/Android