分析输入输出
//输入
var arr = [1,2,[3,4,5,[6,7,8],9],10,[11,12]];
//输出
[1,2,3,4,5,6,7,8,9,10,11,12]
方法一(递归)
降低N个维度
function flat(arr){
if(Object.prototype.toString.call(arr) != "[object Array]"){return false};
let res = [];
for(var i=0;i<arr.length;i++){
if(arr[i] instanceof Array){
res = res.concat(flat(arr[i]))
}else{
res.push(arr[i])
}
}
return res;
};
var arr = [1,2,[3,4,5,[6,7,8],9],10,[11,12]];
flat(arr);
//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
注意:
- 数组连接用concat,保证数组的原有维度不变
- push会改变原始数据,并且没有铺平数组的功能,你传什么进去,就是什么。会导致数组的维度发生变化,增加了数组的维度
方法二(扩展运算符)
...扩展运算符,只适合降低一个维度。
function flat(arr){
if(Object.prototype.toString.call(arr) != "[object Array]"){return false};
let res=[];
arr.map(item=>{
if(item instanceof Array){
res.push(...item);//展开数组[11,12] 为11,12
}else{
res.push(item)
}
});
return res;
};
var arr = [1,2,[3,4,5,[6,7,8],9],10,[11,12]];
flat(arr);
//[1, 2, 3, 4, 5, Array(3), 9, 10, 11, 12]
方法三(递归+扩展运算符)
降低N个维度
function flat(arr){
if(Object.prototype.toString.call(arr) != "[object Array]"){return false};
let res=[];
arr.map(item=>{
if(item instanceof Array){
res.push(...flat(item));
}else{
res.push(item)
}
});
return res;
};
var arr = [1,2,[3,4,5,[6,7,8],9],10,[11,12]];
flat(arr);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
方法四(递归+reduce)
降低N个维度
function flat(arr){
if(Object.prototype.toString.call(arr) != "[object Array]"){return false};
let res = arr.reduce((prev,cur)=>{
return prev.concat(Array.isArray(cur) ? flat(cur) : cur)
},[])
return res;
};
var arr = [1,2,[3,4,5,[6,7,8],9],10,[11,12]];
flat(arr);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
reduce内部也可这么写
[...a,...b] 其作用相当于a.concat(b),这种用法更加直观明了
if(!Array.isArray(cur)){
return [...prev,cur];
}else{
return [...prev,...flat(cur)]
}
reduce((prev,cur,index,arr)=>{},init)用法
- 两个参数,一个callback,一个初始值
- 回调的四个参数分别为,上一次 return的结果,当前项,当前索引,数组,还有初始值。
- reduce实现什么功能取决于回调内部做了什么
方法五(toString+split)
toString可直接去除掉中括号
var arr = [1,2,[3,4,5,[6,7,8],9],10,[11,12]];
var arr1 = arr.toString().split(',').map((val)=>{
return parseInt(val)
});
console.log(arr1);
//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
//思路
[1,2,[3,4,5,[6,7,8],9],10,[11,12]].toString().split(",")
// ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]
[1,2,[3,4,5,[6,7,8],9],10,[11,12]].toString()
//"1,2,3,4,5,6,7,8,9,10,11,12"
方法六(原生的flat)
参数为层数(默认一层)
[1,2,[3]].flat()
// [1, 2, 3]
[1,2,[3,[4]]].flat(2)
// [1, 2, 3, 4]
方法七(while+some+apply)
function flat(arr){
while(arr.some(item => Array.isArray(item))){
arr = [].concat.apply([],arr);
}
return arr;
}
var arr = [1,2,[3,4,5,[6,7,8],9],10,[11,12]];
flat(arr);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
方法八
let arr = [[1, 2], 3, [[[4], 5]]];
function flat(arr) {
return [].concat(
...arr.map(x => Array.isArray(x) ? flat(x) : x)
)
};
flat(arr);// [1,2,3,4,5]
总结
- 建议少使用递归
- 建议使用toString直接干掉中括号,得到字符串,再转为数组