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 相关文章推荐
ie 调试javascript的工具
Apr 29 Javascript
让JavaScript 轻松支持函数重载 (Part 1 - 设计)
Aug 04 Javascript
javascript天然的迭代器
Oct 29 Javascript
『jQuery』取指定url格式及分割函数应用
Apr 22 Javascript
jquery parent和parents的区别分析
Oct 02 Javascript
iframe的onreadystatechange事件在firefox下的使用
Apr 16 Javascript
ionic App问题总结系列之ionic点击系统返回键退出App
Aug 19 Javascript
jQuery实现滚动到底部时自动加载更多的方法示例
Feb 18 jQuery
JS高级技巧(简洁版)
Jul 29 Javascript
cdn模式下vue的基本用法详解
Oct 07 Javascript
vue组件中的样式属性scoped实例详解
Oct 30 Javascript
如何使用Javascript中的this关键字
May 28 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
浅析THINKPHP的addAll支持的最大数据量
2015/02/03 PHP
PHP中使用register_shutdown_function函数截获fatal error示例
2015/04/21 PHP
php利用fsockopen GET/POST提交表单及上传文件
2017/05/22 PHP
php注册审核重点解析(数据访问)
2017/05/23 PHP
PHP使用redis位图bitMap 实现签到功能
2019/10/08 PHP
javascript 写类方式之八
2009/07/05 Javascript
JavaScript 解析读取XML文档 实例代码
2009/07/07 Javascript
jquery中使用ajax获取远程页面信息
2011/11/13 Javascript
jquery prop的使用介绍及与attr的区别
2013/12/19 Javascript
js实现鼠标滑过文字链接色彩变化的效果
2015/05/06 Javascript
jQuery插件HighCharts实现的2D回归直线散点效果示例【附demo源码下载】
2017/03/09 Javascript
AngulaJS路由 ui-router 传参实例
2017/04/28 Javascript
webpack 单独打包指定JS文件的方法
2018/02/22 Javascript
vue-cli配置flexible过程详解
2019/07/04 Javascript
JS实现导航栏楼层特效
2020/01/01 Javascript
vue-resource post数据时碰到Django csrf问题的解决
2020/03/13 Javascript
基于js判断浏览器是否支持webGL
2020/04/18 Javascript
记一次vue跨域的解决
2020/10/21 Javascript
[50:01]Ti4 冒泡赛第二天 NEWBEE vs Titan
2014/07/15 DOTA
[02:38]2018DOTA2亚洲邀请赛赛前采访-VGJ.T
2018/04/03 DOTA
Python删除指定目录下过期文件的2个脚本分享
2014/04/10 Python
python使用clear方法清除字典内全部数据实例
2015/07/11 Python
Python实现爬虫从网络上下载文档的实例代码
2018/06/13 Python
django2+uwsgi+nginx上线部署到服务器Ubuntu16.04
2018/06/26 Python
python3实现网络爬虫之BeautifulSoup使用详解
2018/12/19 Python
使用Python完成15位18位身份证的互转功能
2019/11/06 Python
Python嵌入C/C++进行开发详解
2020/06/09 Python
使用Django的JsonResponse返回数据的实现
2021/01/15 Python
Under Armour安德玛英国官网:美国高端运动科技品牌
2018/09/17 全球购物
意大利独特而优质的家居用品:Fazzini
2018/12/05 全球购物
介绍一下SQL Server里面的索引视图
2016/07/31 面试题
应聘编辑职位自荐信范文
2014/01/05 职场文书
应届毕业生自荐信
2014/05/28 职场文书
Python实现文本文件拆分写入到多个文本文件的方法
2021/04/18 Python
详解CSS不定宽溢出文本适配滚动
2021/05/24 HTML / CSS
六个好看实用的 HTML + CSS 后台登录入口页面
2022/04/28 HTML / CSS