每日小知识(JavaScript篇) -- 递归拼接树形结构和将树形结构转换为扁平数组结构

  • Array.push()会在数组尾部添加元素,并且返回数组长度

    • 打印Array.push()会得到数组长度

      var arr = ['age'];
      console.log(arr.push('name'));  // 2
      

在这里插入图片描述

  • 要想打印添加元素后的数组,不能直接连带push()一起输出,直接console.log(arr)就行
var data = [
    {id: 1, parent: null, text: '菜单1', children:[
        {id: 13, parent: 1, text: '菜单1-3'},
    ]},
    {id: 11, parent: 1, text: '菜单1-1', children:[
        {id: 112, parent: 11, text: '菜单1-1-2'},
    ]},
    {id: 111, parent: 11, text: '菜单1-1-1'},
    {id: 1121, parent: 112, text: '菜单1-1-2-1'},
    {id: 12, parent: 1, text: '菜单1-2'},
    {id: 2, parent: null, text: '菜单2'},
    {id: 21, parent: 2, text: '菜单2-1'}
]

function getTressList(rootList, parentValue, list){
    for (const item of rootList) {
        if (item.parent == parentValue) {
            list.push(item);
        }
    }

    for (const i of list) {
        // 如果子元素里面存在children就直接递归,不存在就生成一个children
        if (i.children) {
            getTressList(rootList, i.id, i.children);
        }else{
            i.children = [];
            getTressList(rootList, i.id, i.children);
        }

        if (i.children.length == 0) {
            delete i.children
        }
    }

    return list;
}

const resParent = getTressList(data, null, []);
console.log(resParent);

结果
在这里插入图片描述

2. 递归拼接树形结构

2.1 数组扁平化
  • 数组扁平化就是将二维数组变为一维数组
    • 二维数组:var arr = [[1,2,3], [4,5,6]];
    • 一维数组:arr = [1, 2, 3, 4, 5, 6]
  • 实现数组扁平化主要还是遍历二维数组,判断他的元素是不是也是一个数组,不是数组的话就将这个元素存放到一个空数组里,然后不断的遍历数组元素,一遇到不是数组的元素就存放到这个空数组中,遇到是数组的元素就一直遍历他,直到他里面不在存在数组元素
递归
  • 遍历数组的每一项,如果是数组就继续遍历,直到数组元素不在是数组,再用concat将他们拼接在一起

    function flatten(list){
        let newList = [];
        for (const item of list) {
            if (Array.isArray(item)) {
                newList = newList.concat(flatten(item));
            }else{
                newList.push(item);
            }
        }
    
        return newList;
    }
    
    // 测试
    const res = [1, [2,3,4],[5,6]];
    const flattenList = flatten(res);
    console.log(flattenList);	// [1,2,3,4,5,6]
    
  • 代码执行过程:

    • 创建一个空数组:newList
    • 遍历传过来的数组res
      • item = res[0]res[0]不是数组,直接push()newList,此时newList = [1]
      • item = res[1]res[1]是数组,就递归调用flatten继续遍历,此时函数接收的数据就变成了res[1]res[1]的所有元素都不是数组所以直接push()newList,本次循环结束,return newList,此时的newList1 = [2,3,4](为了跟父数组遍历得到的newList进行区分,子元素数组遍历return的结果用newList1代替)
      • 回到最开始数组res的循环,重新遍历完res[1]后,将得到的newList1 = [2,3,4]使用concat()newList = [1]拼接,得到newList = [1,2,3,4]
      • item = res[2]res[2]是数组,遍历步骤跟res[1]的情况一样,最终会得到newList2 = [5,6],同样使用concat()进行数组拼接,最后得到最终结果newList = [1,2,3,4,5,6]
拓展运算符
  • 使用some()检测数组中的元素是否也是数组

  • 是的话就进入while循环,使用拓展运算符展开list

    • concat()用于数组元素拼接,他接受任意数量的参数 —— 数组或值都可以

    • 示例中list = [1, [2,3,4],[5,6]],不使用...展开的话,拼接就只会把一整个list赋值到空数组[]中,得到的结果跟原来的list没什么区别,即使list里的元素也是数组,concat也不会自己展开他里面的数组,他能做的就是把数组[]跟数组list拼接在一起,至于list里的元素是怎样的他并不关心

      // 不使用拓展运算符
      list = [].concat(list);
      list = [].concat([1, [2,3,4],[5,6]]);	// [1, [2,3,4],[5,6]];
      
      // 使用拓展运算符
      list = [].concat(...list);
      list = [].concat(1, [2,3,4],[5,6]);		// 1,2,3,4,5,6
      
function flatten(list){
    while(list.some(item => Array.isArray(item))){
        list = [].concat(...list);
    }
    return list;
}
const res = [1, [2,3,4],[5,6]];
const flattenList = flatten(res);
console.log(flattenList);	// [1,2,3,4,5,6]
使用reduce()
  • 这个方法跟上面使用递归相似
function flatten(list){
    return list.reduce((pre, cur) => {
        // if (Array.isArray(cur)) {
        //     pre = pre.concat(flatten(cur));
        // }else{
        //     pre.push(cur);
        // }
        // return pre;
        return pre.concat(Array.isArray(cur ? flatten(cur) : cur));
    }, [])
}
const res = [1, [2,3,4],[5,6,[7,8]]];
const flattenList = flatten(res);
console.log(flattenList);
使用split和toString
  • 将二维数组转换为字符串,再使用split()进行分割,分割完后的到的数组元素是字符串,在使用map遍历得到的字符串数组,将元素转换为数字
function flatten(list){
    return list.toString().split(',').map(item => Number(item))
}
const res = [1, [2,3,4],[5,6,[7,8]]];
const flattenList = flatten(res);
console.log(flattenList);
2.2 练习:将树形结构转换为扁平数组结构
  • 1.递归拼接树形结构得到的结果resParent进行扁平化
使用reduce
function flatten(list){
    return list.reduce((pre, cur) => {
        const {id, parent, text, children = []} = cur;
        return pre.concat([{id, parent, text}], flatten(children));
    }, [])
}
  • 使用解构赋值,将数组list的元素cur里的每一个属性都赋值给id, parent, text, children = []等变量
  • 刚开始的时候pre是一个空数组[]cur的值为{id: 1, parent: null, text: "菜单1", children: Array(3)}
  • 后面pre的值都是上一次运算的结果
使用递归
function flatten(list){
    // 存放所有的list[i]
    let newList = [];
    // 存放含有children的list[i]
    let parentList = [];
    for(let i = 0; i < list.length; i++){
        // 判断list[i].children是否是数组,是的话就再次遍历list[i].children,直到他里面不存在list[i].children为数组
        // 遇到list[i].children是数组的list[i],就把他里面的children属性删除掉了在push进parentList
        if (Array.isArray(list[i].children)){
            newList = newList.concat(flatten(list[i].children));
            delete list[i].children;
            parentList.push(list[i]);
        } else {
            newList.push(list[i]);
        }
    }

    return newList.concat(parentList);
}
  • 最终结果
    在这里插入图片描述
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值