欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-06-11 18:05:26
Hello, 大噶好, 小葵花妈妈课堂开课啦。。。。。。 我们日常工作中拿到的数据不可能是只有一维的平面数组, 百分之99.99 是数组里嵌套数组再套数组的n维数组 ............................. 这种让人想问候它xx的多维数组我们怎么把它变成一维数组, 也就是只有一个中 ......

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 都  去掉  , 一句话 搞定  !!!