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学习笔记(十七) 检测浏览器插件代码
Jun 20 Javascript
JavaScript编写推箱子游戏
Jul 07 Javascript
jquery实现简单的全选和反选功能
Jan 02 Javascript
老生常谈javascript的类型转换
Oct 12 Javascript
解析ajaxFileUpload 异步上传文件简单使用
Dec 30 Javascript
JavaScript正则替换HTML标签功能示例
Mar 02 Javascript
ES6 Promise对象概念与用法分析
Apr 01 Javascript
AngularJS实现的输入框字数限制提醒功能示例
Oct 26 Javascript
AjaxUpLoad.js实现文件上传功能
Mar 02 Javascript
jquery实现动态添加附件功能
Oct 23 jQuery
VUE中的v-if与v-show区别介绍
Mar 13 Vue.js
JS实现简单的九宫格抽奖
Jun 28 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
一致性哈希算法以及其PHP实现详细解析
2013/08/24 PHP
PHP生成不重复标识符的方法
2014/11/21 PHP
PHP中异常处理的一些方法整理
2015/07/03 PHP
javascript支持firefox,ie7页面布局拖拽效果代码
2007/12/20 Javascript
javascript下判断一个对象是否具有指定名称的属性的的代码
2010/01/11 Javascript
理解Javascript_15_作用域分配与变量访问规则,再送个闭包
2010/10/20 Javascript
jQuery EasyUI API 中文文档 - Tabs标签页/选项卡
2011/10/01 Javascript
JavaScript改变HTML元素的样式改变CSS及元素属性
2013/11/12 Javascript
JQuery中使用.each()遍历元素学习笔记
2014/11/08 Javascript
JavaScript通过prototype给对象定义属性用法实例
2015/03/23 Javascript
分享一个插件实现水珠自动下落效果
2016/06/01 Javascript
Vue.js绑定HTML class数组语法错误的原因分析
2016/10/19 Javascript
jQuery源码分析之init的详细介绍
2017/02/13 Javascript
Angular2下使用pdf插件的方法详解
2017/04/29 Javascript
JS实现标签页切换效果
2017/05/04 Javascript
jQuery实现鼠标滑过商品小图片上显示对应大图片功能【测试可用】
2018/04/27 jQuery
javascript数组去重方法总结(推荐)
2019/03/20 Javascript
Vue实现计算器计算效果
2020/08/17 Javascript
小程序自定义弹框效果
2020/11/16 Javascript
python列表操作实例
2015/01/14 Python
Python变量和数据类型详解
2017/02/15 Python
Python实现简单求解给定整数的质因数算法示例
2018/03/25 Python
python绘制地震散点图
2019/06/18 Python
Python pandas实现excel工作表合并功能详解
2019/08/29 Python
Python容器类型公共方法总结
2020/08/19 Python
Python尾递归优化实现代码及原理详解
2020/10/09 Python
python实现测试工具(二)——简单的ui测试工具
2020/10/19 Python
中国旅游网站:途牛旅游网
2019/09/29 全球购物
Yankee Candle官网:美国最畅销蜡烛品牌之一
2020/01/05 全球购物
专升本自我鉴定
2013/10/10 职场文书
班级口号大全
2014/06/09 职场文书
毕业实习自我鉴定范文2014
2014/09/26 职场文书
2014年办公室文秘工作总结
2014/12/09 职场文书
Python使用OpenCV实现虚拟缩放效果
2022/02/28 Python
SpringBoot整合minio快速入门教程(代码示例)
2022/04/03 Java/Android
Spring Boot接口定义和全局异常统一处理
2022/04/20 Java/Android