JavaScript前端面试扁平数据转tree与tree数据扁平化


Posted in Javascript onJune 14, 2022

一、写在前面

有时我们拿到的数据的数据结构可能不是理想的,那么此时就要求前端程序员,具有改造数据的能力。例如拿到扁平的数据, 但我们要应用在 tree 树形组件或 Cascader 级联选择器组件中,这样的组件要求数据结构是非扁平的的具有层级递进关系的 tree 结构。

总之就是说,提供数据的接口给到的数据,未必符合要求,而当我们又无法令他人为为我们改变时,需求和要求就来到了前端程序员这里, 所以得具备这样的数据处理能力。

下面是将举两个数据改造的例子:

  • 一是扁平化,具有层级递进关系的 tree 数据,转换为扁平结构的的 flat 数据
  • 二是反扁平化,扁平结构的 flat 数据,转换为具有层级递进关系的 tree 数据

二、正文部分

2.1 扁平数据转为 tree 数据

扁平化函数

/**
   * 扁平化:将具有层级递进关系结构的 tree 数据扁平化
   * 
   * @param treeList 有层级递进关系结构的 tree 数据
   * @param flatList 用于接收扁平化结果的变量
   * @returns {*} 返回扁平化结果
   */
  function treeToFlat (treeList, flatList) {
    // flatList.length > 9999 是考虑底线保护原则,出于极限保护的目的设置的,可不设或按需设置。
    if (flatList.length > 9999) {
      return
    }
    treeList.map(e => {
      flatList.push(e)
      // 递归:有条件的自己调用自己,条件是 e.children.length 为真
      if (e.children && e.children.length) {
        treeToFlat(e.children, flatList)
      }
    })
    // console.log('扁平化后:', flatList)
    return flatList
  }

2.2 tree 数据转为扁平数据

反扁平化函数

/**
   * 反扁平化:将扁平结构的 flat 数据转换为具有层级递进关系结构的 tree 数据
   * 
   * @param flatList 扁平结构的数据
   * @param treeList 用于接收反扁平化结果的变量
   * @returns {*} 返回反扁平化结果
   */
  function flatToTree (flatList, treeList) {
    flatList.map(e => {
      // 以 e.pid===null,作为判断是不是根节点的依据,或者直接写死根节点(如果确定的话),
      // 具体以什么作为判断根节点的依据,得看数据的设计规则,通常是判断层级或是否代表根节点的标记
      if (e.pid === null) {
        // 避免出现重复数据
        const index = treeList.findIndex(sub => sub.id === e.id)
        if (index === -1) {
          treeList.push(e)
        }
      }
      flatList.map(e2 => {
        if (e2.pid === e.id) {
          // 避免出现重复数据
          const index = e.children.findIndex(sub => sub.id === e2.id)
          if (index === -1) {
            e.children.push(e2)
          }
        }
      })
    })

2.3 完整测试 demo

demo 测试结果截图如下:

JavaScript前端面试扁平数据转tree与tree数据扁平化

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>扁平数据转tree与tree数据扁平化 Demo</title>
</head>
<body>
<h1>扁平数据转tree与tree数据扁平化</h1>
<script>
  window.onload = function () {
    test()
  }
  function test () {
    let flatList = [],
      treeList = [
        {
          id: 1,
          pid: null,
          label: '第一层',
          value: '1',
          children: [
            {
              id: 2,
              pid: 1,
              label: '第二层1',
              value: '2.1',
              children: []
            },
            {
              id: 3,
              pid: 1,
              label: '第二层2',
              value: '2.2',
              children: []
            },
            {
              id: 4,
              pid: 1,
              label: '第二层3',
              value: '2.3',
              children: [
                {
                  id: 5,
                  pid: 4,
                  label: '第三层1',
                  value: '3.1',
                  children: []
                },
                {
                  id: 6,
                  pid: 4,
                  label: '第三层2',
                  value: '3.2',
                  children: []
                },
              ]
            },
          ]
        }
      ]
    console.log('原始 tree 数据:', JSON.parse(JSON.stringify(treeList)))
    // 扁平化
    console.log('tree =>flat,扁平化后:', treeToFlat(JSON.parse(JSON.stringify(treeList)), flatList))
    // 反扁平化,SON.parse(JSON.stringify()) 为了实现深拷贝
    console.log('flat =>tree,反扁平化后:', flatToTree(JSON.parse(JSON.stringify(flatList)), treeList))
  }
  /**
   * 扁平化:将具有层级递进关系结构的 tree 数据扁平化
   * 
   * @param treeList 有层级递进关系结构的 tree 数据
   * @param flatList 用于接收扁平化结果的变量
   * @returns {*} 返回扁平化结果
   */
  function treeToFlat (treeList, flatList) {
    // flatList.length > 9999 是考虑底线保护原则,出于极限保护的目的设置的,可不设或按需设置。
    if (flatList.length > 9999) {
      return
    }
    treeList.map(e => {
      flatList.push(e)
      // 递归:有条件的自己调用自己,条件是 e.children.length 为真
      if (e.children && e.children.length) {
        treeToFlat(e.children, flatList)
      }
    })
    // console.log('扁平化后:', flatList)
    return flatList
  }
  /**
   * 反扁平化:将扁平结构的 flat 数据转换为具有层级递进关系结构的 tree 数据
   * 
   * @param flatList 扁平结构的数据
   * @param treeList 用于接收反扁平化结果的变量
   * @returns {*} 返回反扁平化结果
   */
  function flatToTree (flatList, treeList) {
    flatList.map(e => {
      // 以 e.pid===null,作为判断是不是根节点的依据,或者直接写死根节点(如果确定的话),
      // 具体以什么作为判断根节点的依据,得看数据的设计规则,通常是判断层级或是否代表根节点的标记
      if (e.pid === null) {
        // 避免出现重复数据
        const index = treeList.findIndex(sub => sub.id === e.id)
        if (index === -1) {
          treeList.push(e)
        }
      }
      flatList.map(e2 => {
        if (e2.pid === e.id) {
          // 避免出现重复数据
          const index = e.children.findIndex(sub => sub.id === e2.id)
          if (index === -1) {
            e.children.push(e2)
          }
        }
      })
    })
    // console.log('反扁平化后:', treeList)
    return treeList
  }
</script>
</body>
</html>

三、写在后面

这两个扁平化与反扁平化写法,感觉还有值得优化的方法,但暂时想不到。

此外,递归的应用也是值得注意的地方。

我理解的递归:有条件的自己调用自己

以上就是JavaScript前端面试扁平数据转tree与tree数据扁平化的详细内容,更多关于扁平数据转tree数据扁平化的资料请关注三水点靠木其它相关文章!


Tags in this post...

Javascript 相关文章推荐
破除网页鼠标右键被禁用的绝招大全
Dec 27 Javascript
基于jquery的兼容各种浏览器的iframe自适应高度的脚本
Aug 13 Javascript
jQuery插件实现多级联动菜单效果
Dec 01 Javascript
jQuery前端开发35个小技巧
May 24 Javascript
js对字符串进行编码的方法总结(推荐)
Nov 10 Javascript
Angular 向组件传递模板的两种方法
Feb 23 Javascript
Vue封装一个简单轻量的上传文件组件的示例
Mar 21 Javascript
JS中获取 DOM 元素的绝对位置实例详解
Apr 23 Javascript
javascript显示动态时间的方法汇总
Jul 06 Javascript
JavaScript中关于base64的一些事
May 06 Javascript
微信小程序后端(java)开发流程的详细步骤
Nov 13 Javascript
微信小程序服务器日期格式化问题
Jan 07 Javascript
vue如何在data中引入图片的正确路径
Jun 05 #Vue.js
Vue Mint UI mt-swipe的使用方式
Jun 05 #Vue.js
vue @ ~ 相对路径 路径别名设置方式
Jun 05 #Vue.js
vue css 相对路径导入问题级踩坑记录
Jun 05 #Vue.js
vue中data里面的数据相互使用方式
Jun 05 #Vue.js
Vue 打包后相对路径的引用问题
Jun 05 #Vue.js
vue实现在data里引入相对路径
Jun 05 #Vue.js
You might like
通过5个php实例细致说明传值与传引用的区别
2012/08/08 PHP
php对二维数组按指定键值key排序示例代码
2013/11/26 PHP
php实现的简单美国商品税计算函数
2015/07/13 PHP
值得分享的php+ajax实时聊天室
2016/07/20 PHP
Dojo 学习笔记入门篇 First Dojo Example
2009/11/15 Javascript
JavaScript 滚轮事件使用说明
2010/03/07 Javascript
Jquery如何实现点击时高亮显示代码
2014/01/22 Javascript
jquery实现侧边弹出的垂直导航
2014/12/09 Javascript
JS使用eval解析JSON的注意事项分析
2015/11/14 Javascript
使用jQuery判断Div是否在可视区域的方法 判断div是否可见
2016/02/17 Javascript
js实现tab选项卡切换功能
2017/01/13 Javascript
垃圾回收器的相关知识点总结
2018/05/13 Javascript
vue移动端使用appClound拉起支付宝支付的实现方法
2019/11/21 Javascript
Vue.js仿Select下拉框效果
2020/02/18 Javascript
Python中针对函数处理的特殊方法
2014/03/06 Python
python处理csv数据动态显示曲线实例代码
2018/01/23 Python
TensorFlow损失函数专题详解
2018/04/26 Python
python模拟表单提交登录图书馆
2018/04/27 Python
Python使用Turtle库绘制一棵西兰花
2019/11/23 Python
在Python中通过threshold创建mask方式
2020/02/19 Python
python检查目录文件权限并修改目录文件权限的操作
2020/03/11 Python
Python如何实现大型数组运算(使用NumPy)
2020/07/24 Python
python安装及变量名介绍详解
2020/12/12 Python
纯CSS3实现鼠标悬停提示气泡效果
2014/02/28 HTML / CSS
印度最大的酒店品牌网络:OYO Rooms
2016/07/24 全球购物
凯特王妃父母建立的派对用品网站:Party Pieces
2017/05/28 全球购物
香港优质食材和美酒专门店:FoodWise
2017/09/01 全球购物
优秀医生事迹材料
2014/02/12 职场文书
《闻一多先生的说和做》教学反思
2014/04/28 职场文书
高三励志标语
2014/06/05 职场文书
个人主要事迹材料
2014/08/26 职场文书
民主评议党员自我鉴定
2014/10/21 职场文书
2014幼儿园班主任工作总结
2014/12/04 职场文书
大学生求职自荐信
2015/03/24 职场文书
教师节获奖感言
2015/07/31 职场文书
90后经典动画片排行:《数码宝贝》第二,《小鲤鱼历险记》在榜
2022/03/18 日漫