js数组拍平(数组扁平化)的八种方式

13,688 阅读3分钟

分析输入输出

//输入
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直接干掉中括号,得到字符串,再转为数组