还是照旧贴上写的很好的博客。。。
数组拍平1
接下来就自己复述阶段啦
1、人家数组有自己拍平的方法flat啊,(还用得着自己写?)
arr.flat(Infinity)//不管你多少层都拍成1层
arr.flat(1)// [ 1, [ 2 ], [ 3, [ 4, 5 ] ] ]=>[ 1, 2, 3, [ 4, 5 ] ],只拍平了第一层的元素
arr.flat()//不传值,默认为arr.flat(1)
要注意的一个点啦:
arr.flat()
是返回值新的改变的数组,但是原来的数组并没有改变哦。- 如果原数组有空位,flat()方法会跳过空位。
[1, 2, , 4, 5].flat()
// [1, 2, 4, 5]
2、朴素的处理方式(递归)
function fn(arr) {
let arr1 = []
arr.forEach((val) => {
if (val instanceof Array) {
arr1 = arr1.concat(fn(val))
} else {
arr1.push(val)
}
})
return arr1
}
3、把递归讲的更高大上的方式(+reduce)
利用reduce,就省掉了定义新数组,循环的书写,实际上还是一样一样的内涵啦。
function fn(arr) {
return arr.reduce((prev, cur) => {
return prev.concat(Array.isArray(cur) ? fn(cur) : cur)
}, [])
}
如果用上面那种?:的话,递归也可以写成
function fn(arr) {
let arr1 = []
arr.forEach((val) => {
Array.isArray(val) ? arr1 = arr1.concat(fn(val)) : arr1.push(val)
})
return arr1
}
差别就是reduce自带初始化格式,递归还是第一种吧,比较明了啊
4、拓展运算符+while循环
原理:扩展运算符也是拍平一层的作用,所以要用while循环,循环的条件就是还有元素是数组的样子。
//ary.some(Array.isArray)等于ary.some((val) => Array.isArray(val))
while (ary.some(Array.isArray)) {
ary = [].concat(...ary);//...作为参数传入,拼接数组和字符,即可拍平一层
}
所以,如果要模拟flat函数的话,扩展运算符应该是最方便的一种方法。
Array.prototype.myflat = function (k) {
let temp = this//指向调用这个函数的数组
while (k > 0) {
temp = [].concat(...temp)
k--
}
return temp
}
5、奇技淫巧之toString+split
原理:转成字符后,然后以逗号分隔即可。
//[1, 2, 3, 4].toString()=>1,2,3,4
let arr1 = arr.toString().split(',').map((val) => {
return parseInt(val)
})
注意点:不一定返回的是parseInt后的val,如果是字符类型直接return val即可。
6、奇技淫巧之JSON.stringify()+replace+split
原理:同样是转字符,但是这个方法是连带数组的[]都包括的。所以,加上splice来去掉比较合适。
//JSON.stringify([1, 2, 3, 4]) =>[1,2,3,4]
let str = JSON.stringify(arr)
let arr1 = str.replace(/\[|\]/g, '').split(',').map(val => parseInt(val))
以上。