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 相关文章推荐
jquery实现加载等待效果示例
Sep 25 Javascript
JavaScript设计模式之策略模式实例
Oct 10 Javascript
JQuery右键菜单插件ContextMenu使用指南
Dec 19 Javascript
浅谈javascript的分号的使用
May 12 Javascript
基于JavaScript实现网页倒计时自动跳转代码
Dec 28 Javascript
第一次接触神奇的Bootstrap菜单和导航
Aug 01 Javascript
js实现把图片的绝对路径转为base64字符串、blob对象再上传
Dec 29 Javascript
js实现tab选项卡切换功能
Jan 13 Javascript
Vue开发中整合axios的文件整理
Apr 29 Javascript
react-native组件中NavigatorIOS和ListView结合使用的方法
Sep 30 Javascript
浅谈Vue3.0新版API之composition-api入坑指南
Apr 30 Javascript
vue 动态添加class,三个以上的条件做判断方式
Nov 02 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
Windows PHP5和Apache的安装与配置
2009/06/08 PHP
php 网页游戏开发入门教程一(webgame+design)
2009/10/26 PHP
浅谈php中变量的数据类型判断函数
2017/03/04 PHP
PHP基于自定义函数实现的汉字转拼音功能实例
2017/09/30 PHP
验证码按回车不变解决方法
2013/03/29 Javascript
javascript获得网页窗口实际大小的示例代码
2013/09/21 Javascript
js整数字符串转换为金额类型数据(示例代码)
2013/12/26 Javascript
使用upstart把nodejs应用封装为系统服务实例
2014/06/01 NodeJs
EasyUI中combobox默认值注意事项
2015/03/01 Javascript
深入探寻seajs的模块化与加载方式
2015/04/14 Javascript
jQuery图片旋转插件jQueryRotate.js用法实例(附demo下载)
2016/01/21 Javascript
jQuery的ajax和遍历数组json实例代码
2016/08/01 Javascript
原生js实现打字动画游戏
2017/02/04 Javascript
javascript实现数据双向绑定的三种方式小结
2017/03/09 Javascript
微信小程序实现点击文字页面跳转功能【附源码下载】
2017/12/12 Javascript
js实现图片上传即时显示效果
2019/09/30 Javascript
[38:40]2018DOTA2亚洲邀请赛 4.6淘汰赛 mineski vs LGD 第一场
2018/04/10 DOTA
[40:19]完美世界DOTA2联赛PWL S3 Rebirth vs CPG 第二场 12.18
2020/12/19 DOTA
Python创建文件和追加文件内容实例
2014/10/21 Python
Python处理JSON数据并生成条形图
2016/08/05 Python
python 实现上传图片并预览的3种方法(推荐)
2017/07/14 Python
Python读取图片为16进制表示简单代码
2018/01/19 Python
Python Flask基础教程示例代码
2018/02/07 Python
基于python requests库中的代理实例讲解
2018/05/07 Python
python tkinter实现界面切换的示例代码
2019/06/14 Python
Python 生成器,迭代,yield关键字,send()传参给yield语句操作示例
2019/10/12 Python
CSS3选择器新增问题的实现
2021/01/21 HTML / CSS
师范毕业生自荐信
2013/10/17 职场文书
项目合作意向书范本
2014/04/01 职场文书
入股协议书
2014/04/14 职场文书
《望庐山瀑布》教学反思
2014/04/22 职场文书
小学课外活动总结
2014/07/09 职场文书
2015年度信用社工作总结
2015/05/04 职场文书
奠基仪式致辞
2015/07/30 职场文书
2019餐饮行业创业计划书!
2019/06/27 职场文书
《进击的巨人》新联动CM 兵长强势出击兽巨人
2022/04/05 日漫