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 相关文章推荐
永不消失的title提示代码
Feb 15 Javascript
基于jquery的用鼠标画出可移动的div
Sep 06 Javascript
jquery简单实现网页层的展开与收缩效果
Aug 07 Javascript
jQuery div拖拽用法实例
Jan 14 Javascript
js判断是否为空和typeof的用法(详解)
Oct 07 Javascript
使用Angular.js实现简单的购物车功能
Nov 21 Javascript
JavaScript中object和Object的区别(详解)
Feb 27 Javascript
bootstrapvalidator之API学习教程
Jun 29 Javascript
使用mint-ui开发项目的一些心得(分享)
Sep 07 Javascript
详解ES6 Symbol 的用途
Oct 14 Javascript
深入浅析Node.js 事件循环、定时器和process.nextTick()
Oct 22 Javascript
JS关闭子窗口并且刷新上一个窗口的实现示例
Mar 10 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
编译问题
2006/10/09 PHP
php FLEA中二叉树数组的遍历输出
2012/09/26 PHP
php实现smarty模板无限极分类的方法
2015/12/07 PHP
javascript 面向对象编程  function是方法(函数)
2009/09/17 Javascript
该如何加载google-analytics(或其他第三方)的JS
2010/05/13 Javascript
js防止表单重复提交实现代码
2012/09/05 Javascript
javascript 手动给表增加数据的小例子
2013/07/10 Javascript
Javascript中arguments和arguments.callee的区别浅析
2015/04/24 Javascript
JS实现从顶部下拉显示的带动画QQ客服特效代码
2015/10/24 Javascript
javascript实现随机显示星星特效
2016/01/28 Javascript
开启BootStrap学习之旅
2016/05/04 Javascript
AngularJS入门教程之双向绑定详解
2016/08/18 Javascript
bootstrap模态框消失问题的解决方法
2016/12/02 Javascript
Vue利用路由钩子token过期后跳转到登录页的实例
2017/10/26 Javascript
Vue官方文档梳理之全局配置
2017/11/22 Javascript
js提取中文拼音首字母的封装工具类
2018/03/12 Javascript
vue.js实现格式化时间并每秒更新显示功能示例
2018/07/07 Javascript
jQuery.extend 与 jQuery.fn.extend的用法及区别实例分析
2018/07/25 jQuery
vue移动端html5页面根据屏幕适配的四种解决方法
2018/10/19 Javascript
ant-design-vue 时间选择器赋值默认时间的操作
2020/10/27 Javascript
Python实现删除Android工程中的冗余字符串
2015/01/19 Python
基础的十进制按位运算总结与在Python中的计算示例
2016/06/28 Python
Python字典对象实现原理详解
2019/07/01 Python
python3 Scrapy爬虫框架ip代理配置的方法
2020/01/17 Python
欧洲最大的化妆品连锁公司:Douglas道格拉斯
2017/05/06 全球购物
FC-Moto丹麦:欧洲最大的摩托车服装和头盔商店之一
2019/08/20 全球购物
Luxplus荷兰:以会员价购买美容产品等,独家优惠
2019/08/30 全球购物
中专生职业生涯规划书范文
2013/12/29 职场文书
女子职高个人自荐书
2014/02/01 职场文书
2014年大学生党员评议表自我评价
2014/09/20 职场文书
投标文件签署授权委托书范本
2014/10/12 职场文书
2015年医务人员医德医风自我评价
2015/03/03 职场文书
通知书大全
2015/04/27 职场文书
欠款起诉书范文
2015/05/19 职场文书
vue点击弹窗自动触发点击事件的解决办法(模拟场景)
2021/05/25 Vue.js
JavaScript实现栈结构详细过程
2021/12/06 Javascript