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 相关文章推荐
浅析JavaScript声明变量
Dec 21 Javascript
关于javascript原型的修改与重写(覆盖)差别详解
Aug 31 Javascript
JavaScript学习笔记--常用的互动方法
Dec 07 Javascript
JavaScript中数据类型转换总结
Dec 25 Javascript
详解Angular Reactive Form 表单验证
Jul 06 Javascript
js移动端事件基础及常用事件库详解
Aug 15 Javascript
实例学习JavaScript读取和写入cookie
Jan 29 Javascript
vue实现学生录入系统之添加删除功能
Jul 11 Javascript
vscode中vue-cli项目es-lint的配置方法
Jul 30 Javascript
JS+HTML5 Canvas实现简单的写字板功能示例
Aug 30 Javascript
vue使用el-upload上传文件及Feign服务间传递文件的方法
Mar 15 Javascript
解决vue cli使用typescript后打包巨慢的问题
Sep 30 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
欧美媒体选出10年前最流行的17部动画
2017/01/18 日漫
收藏的PHP常用函数 推荐收藏保存
2010/02/21 PHP
PHP初学者常见问题集合 修正版(21问答)
2010/03/23 PHP
PHP Array交叉表实现代码
2010/08/05 PHP
php实现基于微信公众平台开发SDK(demo)扩展的方法
2014/12/22 PHP
PHP-FPM 设置多pool及配置文件重写操作示例
2019/10/02 PHP
为Extjs加加速(javascript加速)
2010/08/19 Javascript
javascript中如何处理引号编码&amp;#034;
2013/08/15 Javascript
使用JavaScript获取电池状态的方法
2014/05/03 Javascript
js实现双击图片放大单击缩小的方法
2015/02/17 Javascript
javascript html实现网页版日历代码
2016/03/08 Javascript
ichart.js绘制虚线、平均分虚线效果的实现代码
2016/05/05 Javascript
浅谈JavaScript 数据属性和访问器属性
2016/09/01 Javascript
原生JS实现匀速图片轮播动画
2016/10/18 Javascript
Vue.js开发环境搭建
2016/11/10 Javascript
JS获取多维数组中相同键的值实现方法示例
2017/01/06 Javascript
js实现上下左右弹框划出效果
2017/03/08 Javascript
详解用node-images 打造简易图片服务器
2017/05/08 Javascript
基于Vue2x的图片预览插件的示例代码
2018/05/14 Javascript
Mpvue中使用Vant Weapp组件库的方法步骤
2019/05/16 Javascript
js实现无缝滚动双图切换效果
2019/07/09 Javascript
[00:12]DAC2018 Miracle-站上中单舞台,他能否再写奇迹?
2018/04/06 DOTA
Python中使用装饰器来优化尾递归的示例
2016/06/18 Python
python中urlparse模块介绍与使用示例
2017/11/19 Python
解决Mac安装scrapy失败的问题
2018/06/13 Python
在Python 中实现图片加框和加字的方法
2019/01/26 Python
Python2.7实现多进程下开发多线程示例
2019/05/31 Python
如何用Matplotlib 画三维图的示例代码
2020/07/28 Python
用python制作个音乐下载器
2021/01/30 Python
网络安全方面的面试题
2016/01/07 面试题
机械专业毕业生推荐信范文
2013/11/25 职场文书
春节晚会主持词
2014/03/24 职场文书
毕业生找工作求职信
2014/08/05 职场文书
社区节水倡议书
2015/04/29 职场文书
会计继续教育培训心得体会
2016/01/19 职场文书
Python函数中的不定长参数相关知识总结
2021/06/24 Python