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