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 DOM 添加事件
Feb 14 Javascript
Javascript new关键字的玄机 以及其它
Aug 25 Javascript
JavaScript中的getDay()方法使用详解
Jun 09 Javascript
jQuery实现仿腾讯视频列表分页效果的方法
Aug 07 Javascript
BootStrap3使用错误记录及解决办法
Dec 22 Javascript
深入理解React Native原生模块与JS模块通信的几种方式
Jul 24 Javascript
Angular js 实现添加用户、修改密码、敏感字、下拉菜单的综合操作方法
Oct 24 Javascript
npm 下载指定版本的组件方法
May 17 Javascript
webpack4.x CommonJS模块化浅析
Nov 09 Javascript
JavaScript实现简单随机点名器
Nov 21 Javascript
解决Vue中使用keepAlive不缓存问题
Aug 04 Javascript
Javascript生成器(Generator)的介绍与使用
Jan 31 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
DOTA2 1月28日更新:监管系统降临刀塔世界
2021/01/28 DOTA
php 结果集的分页实现代码
2009/03/10 PHP
跟我学Laravel之请求与输入
2014/10/15 PHP
php实现MySQL数据库备份与还原类实例
2014/12/09 PHP
推荐5款跨平台的PHP编辑器
2014/12/25 PHP
使用PHP生成二维码的方法汇总
2015/07/22 PHP
yii2高级应用之自定义组件实现全局使用图片上传功能的方法
2016/10/08 PHP
PHP获取数组中单列值的方法
2017/06/10 PHP
js 屏蔽鼠标右键脚本附破解方法
2009/12/03 Javascript
JavaScript 错误处理与调试经验总结
2010/08/10 Javascript
在子窗口中关闭父窗口的一句代码
2013/10/21 Javascript
jquery放大镜效果超漂亮噢
2013/11/15 Javascript
JQuery+Ajax无刷新分页的实例代码
2014/02/08 Javascript
Node.js编码规范
2014/07/14 Javascript
angularJS 中input示例分享
2015/02/09 Javascript
jQuery延迟加载图片插件Lazy Load使用指南
2015/03/25 Javascript
clipboard.js无需Flash无需依赖任何JS库实现文本复制与剪切
2015/10/10 Javascript
基于javascript实现图片滑动效果
2016/05/07 Javascript
jQuery实现简单的tab标签页效果
2016/09/12 Javascript
jquery 实时监听输入框值变化的完美方法(必看)
2017/01/26 Javascript
关于webpack2和模块打包的新手指南(小结)
2017/08/07 Javascript
详解为Bootstrap Modal添加拖拽的方法
2018/01/05 Javascript
详解vue+vuex+koa2开发环境搭建及示例开发
2018/01/22 Javascript
uni-app之APP和小程序微信授权方法
2019/05/09 Javascript
vue 项目软键盘回车触发搜索事件
2020/09/09 Javascript
Vue+Java 通过websocket实现服务器与客户端双向通信操作
2020/09/22 Javascript
[01:02:48]2018DOTA2亚洲邀请赛 4.1 小组赛 A组 LGD vs OG
2018/04/02 DOTA
python模拟登陆阿里妈妈生成商品推广链接
2014/04/03 Python
Python下线程之间的共享和释放示例
2015/05/04 Python
Python绘制七段数码管实例代码
2017/12/20 Python
python网络爬虫学习笔记(1)
2018/04/09 Python
Python多进程入门、分布式进程数据共享实例详解
2019/06/03 Python
Canvas实现贝赛尔曲线轨迹动画的示例代码
2019/04/25 HTML / CSS
预防艾滋病宣传标语
2014/06/25 职场文书
党干部专题民主生活会对照检查材料思想汇报
2014/10/06 职场文书
阿里云ECS云服务器快照的概念以及如何使用
2022/04/21 Servers