数据处理之 数组扁平化 (数组降维)顺带总结一下数组的方法

Hello,   大噶好, 小葵花妈妈课堂开课啦。。。。。。

我们日常工作中拿到的数据不可能是只有一维的平面数组, 百分之99.99  是数组里嵌套数组再套数组的n维数组 .............................

这种让人想问候它xx的多维数组我们怎么把它变成一维数组, 也就是只有一个中括号 的数组 呢 ? 

接下来我们 一步一步来实现它 ,  Follow me  

 

讲降维之前,  我们先来回顾一下 数组  有哪些   方法   ?   

给同学们一秒钟时间思考。。。

请同学们 举手回答  。。。。 

OK    为了方便记忆,我们可以把数组的方法分成两类 :

    1  不改变原数组的方法

    2   改变原数组的方法

先说会改变原数组的方法 :  

 sort()   数组的排序方法 , 可以传一个回调函数, 不传参数默认按照字符串的unicode码位点排序

    所以不传参 的话    10  是 小于 2 的  。。。。先比第一位 1 < 2  ,只有第一位相等才会比第二位,

    所以 10 < 2,回调函数接受两个参数, 可以在回调函数中定义排序的规则,  执行后返回改变后的原数组

 

reverse()   数组逆序      执行后返回改变后的原数组

 

pop()   弹出数组的最后一个元素   执行后返回弹出的变量

 

shift()  弹出数组的第一个元素   执行后返回弹出的变量

 

push()  在数组的末尾加(可加多个元素)   执行后返回改变后的原数组的length

 

unshift()  在数组的头部加(可加多个元素)   执行后返回改变后的原数组的length

 

splice(start, deleteCount,  new可选)  用于删除指定区域的元素, 并可以在删除的区域添加新的元素

                  new可以是多个新元素

                  执行后返回被删除的元素

 

copyWithin(start, end可选, stop可选)  复制 index = end 的元素   并  替换 掉 index = start 的元素  ,

            stop 表示 在第几位 停止复制( IE 11 及更早版本不支持 copyWithin() 方法),

            执行后返回改变后的原数组

 

fill(value, start可选, end可选)   把数组的start 位  到 end 位 的元素 都用 value  替换掉  ,

              只传value,数组的所有元素都用value替换,

              执行后返回改变后的原数组

 

不改变原数组的方法:  

concat()        数组合并, 可以传数组也可以传参数列表   , 返回一个合并后的新数组

      如果合并的数组里面有引用值, 新数组中的引用值的地址和原来一样,

      改变其中一个,另一个也会发生改变, 所以并不能用来深拷贝。

      (下一期我们会来讨论一下 深浅拷贝 )

 

includes(value, start可选)    从start处往后查找  value 是否在数组中, 返回一个布尔值

 

indexOf(value, start可选)    从start 开始 往后查找  value,   返回找到的第一个值的索引,

             没找到返回-1

 

lastIndexOf(value, start可选) 从索引为start的元素开始往前查找,返回找到的第一个值的索引,

 

             没找到返回-1

 

 

join(string可选)   把数组里的每一项用string里的符号拼接成一个字符串,

        不传参数用逗号拼接成一个字符串

 

find(callback)   按照callback里的筛选条件返回第一个符合条件的元素

 

findIndex(callback)  按照callback里的筛选条件返回第一个符合条件的元素的索引

 

toString()   把数组转换成字符串 == >  join()  ;

 

slice(start可选, end可选)   从数组索引为start处开始复制到索引为(end - 1)的元素   

             返回一个由复制出来的元素组成的数组,

             不传参数复制整个数组,

            注意:不传参复制的数组内部如果有引用值的话,复制后引用值

            指向同一个地址, 不能实现深拷贝

数组还有很多遍历的方法我就不一一列出来了, 

我们开始进入正题   。。。。。。

和 扁平化  数组有关的方法    : 

  1  flat(deep可选)  deep降维深度  ; deep = 0 不降维

          deep 等于几 就降几维,

          不传deep   降一维

  2  flatMap(callback)   callback 里可以操作数组, 只能降一维

上例子:

1 var a = [1, 2, 3, 4, 5, [2,3,4,[6,10]]];    // 3维数组
2 
3 var b = a.flat(2);  //  参数为  维数  减一
4 console.log(b);  // b = [1, 2, 3, 4, 5, 2, 3, 4, 6, 10]
5 
6 var c = a.flatMap( (value, index, array) => {  //只能用于2维数组的降维
7     return value + 1;
8 });
9 console.log(c); // c = [2, 3, 4, 5, 6, "2,3,4,6,101"]

 

需要注意的是: 

 1   flat 只能用于已知维度的数组降维

 2   flatMap  如果数组内有引用值 , 引用值会先调用toString()方法转换成字符串再进行计算

对于未知维度的数组, 我们需要 借用   reduce()  方法  

reduce(callback, init可选)   俗称累加器   callback里写累加规则,  init 为初始值 

 

//  多维度降维使用递归
deepFlat = (arr) => {
    return arr.reduce((a, b) => {
       return  Array.isArray(b) ? [...a, ...deepFlat(b)] : [...a, b]
    }, [])
};

分析     给一个初始值 [] ,  第一次 a = 初始值[]  , b是数组的第一位  , 判断b是否是数组,

如果是数组,递归继续降维,降维的结果和a 合并

如果不是数组, 直接和a合并,  

合并的结果作为下一次初始值,

第二次 a 为 上一次得到的初始值, b 为数组的第二位, 以此类推 。。。。。。。

这样写有个小问题, 如果第一次传进去的不是数组的话会报错 !

Uncaught TypeError: arr.reduce is not a function

 

所以如果不想加额外的判断的话,还可以这样写

const flattenDeep = (arr) => {
    return Array.isArray(arr) ? arr.reduce((a, b) => { 
        return [...a, ...flattenDeep(b)]
        }, []) : [arr]
    };

再分析    先判断传进来的实参arr是否是数组, 如果不是的话直接返回【arr】,

     如果是的话  再   调用 reduce()方法  进行递归降维 ,

更骚的写法

const flattenDeep = (arr) => Array.isArray(arr) ? arr.reduce((a, b) => [...a, ...flattenDeep(b)], []) : [arr];

把  大括号  和  return 都  去掉  , 一句话 搞定  !!!

 

 

posted @ 2019-03-27 20:04  初心,你好吗  阅读(1133)  评论(2编辑  收藏  举报