你可能遇到的数据扁平化和扁平数据转树状结构一点知识

213 阅读2分钟

一 数据扁平化

第一种方案 es5实现

for循环执行。


 let arr=["砸",'哇','鲁','多','t',["0","k","o"],'t',[[['m',['o','r']]]],'e']

        function flattenFor(arr){
            var flaArr=[];//这里使用let 也行。
            function isArray(item){
                return {}.toString.call(item)==='[object Array]'
                // 万能判断数据类型公式
            }
            for(let k =0;k<arr.length;k++){
                if(isArray(arr[k])){
                    flaArr=flaArr.concat(flattenFor(arr[k]));
                    // 递归每次执行的时候属于是从内往外执行,每次执行都赋值一份最新数据
                }else{
                    flaArr.push(arr[k])
                }
            }
            return flaArr;
        }

       console.log(flattenFor(arr));  
       

第二种方案

forEach 执行,相当于就是把for循环改成forEach;

         arr.forEach((v,index)=>{
                if(isArray(v)){
                    flaArr=flaArr.concat(flattenFor(v));
                }else{
                    flaArr.push(v)
                }
            })

第三种方案

用归纳函数reduce执行;

            function isArray(item){
                return {}.toString.call(item)==='[object Array]'
            }
            function arrReduce(arr){
                let flaArr=[];
                flaArr= arr.reduce(function(prev,cur,index){
                  reduce 每次return的值都会赋值一份给flaArr,然后在跟自己拼接。最简单了。
                    return prev.concat(isArray(cur)?arrReduce(cur):cur)
               },[])  
               return flaArr;
            }

4 es6终极大法:那就是直接用Array.flat();

二 数据菜单扁平数据树状结构

工作中常遇到的扁平数据生成children树状结构。有时候面试也有这个题目。

   let objArr=[        {id:1,name:'节点1',parentId:null},        {id:2,name:"节点2",parentId:1},        {id:3,name:"节点3",parentId:1},        {id:4,name:"节点4",parentId:2},        {id:5,name:"节点5",parentId:2},        {id:6,name:"节点6",parentId:3},        {id:7,name:"节点7",parentId:4},     ]
     //先生成一个根据id取值对应值的函数。
     function filterId(objArr,id){
        return objArr.filter(item=>item.parentId===id)
       }
       function treeChild(arr,parnetId=null){
        let tree=[];
        for(let k in arr){
         //判断是否有子集
            if(filterId(objArr,arr[k].id).length>0){
             //有子集的情况下就设置children
                arr[k].children=filterId(objArr,arr[k].id);
                //如果还有的话直接递归再次执行。
                treeChild(filterId(objArr,arr[k].id));
             }else{
             //没有子集的情况下就放行
                continue
             }
             //不管有没有子集都得放入tree数组。
             tree.push(arr[k]); 
        }
         
         return tree;
       }
     
       console.log(treeChild(objArr));
       打印出来会出现多余出来的
       

结果打印出来多余的1,2,3 些多余出来的数据。这是不够优化的方案,虽然能实现。好处是便于理解。 image.png

优化方案递归执行。

function treeChild(arr, id = null) {
  const tree = [];
  
  // 遍历flatData,找到parentId对应的子节点
  for (const k of arr) {
    if (k.parentId === id) {
      //这里默认数据 null 第一个执行
      // 剩下的都会执行 {} {
      const children = treeChild(flatData, k.id);
      
      // 如果有子节点,则加入children属性中
      if (children.length > 0) {
        k.children = children;
      }
      
      // 加入tree中
      tree.push(k);
    }
  }
  
  return tree;
}

const treeData = flatToTree(flatData);
console.log(treeData); // 输出转换得到的Tree数据