普通递归实现
let arr = [1, [2, [3, 4, 5]]];
function flatten(arr) {
let result = [];
for(let i = 0; i < arr.length; i++) {
// 当前元素是一个数组,对其进行递归展平
if(Array.isArray(arr[i])) {
// 递归展平结果拼接到结果数组
result = result.concat(flatten(arr[i]));
}
// 否则直接加入结果数组
else {
result.push(arr[i]);
}
}
return result;
}
console.log(flatten(a)); // [1, 2, 3, 4,5]
reduce实现
-
JS中的一个函数式编程API -
reduce的第一个参数用来返回最后累加的结果,第二个参数是当前遍历到的元素值
let arr = [1, [2, [3, 4]]];
function flatten(arr) {
return arr.reduce(function(pre, cur){
return pre.concat(Array.isArray(cur) ? flatten(cur) : cur)
}, [])
}
console.log(flatten(arr));// [1, 2, 3, 4,5]
扩展运算符实现
-
some,目的是判断当前数组是否还有数组元素- 有则对数组进行一层展开,同时将展开结果作为下一次判断的条件
let arr = [1, [2, [3, 4]]];
function flatten(arr) {
while (arr.some(i => Array.isArray(i))) {
arr = [].concat(...arr);
}
return arr;
}
console.log(flatten(arr)); // [1, 2, 3, 4,5]
split + toString 实现
-
toString是Object原型链上的方法-
JS中所有对象都派生自Object对象,都能调用toString -
数组的
toString:将数组转换成一个元素间以逗号相隔的字符串- 它内部会先将数组展平成一维后再转换成字符串
-
在
toString过程中会发生类型转换- 对于引用类型转成字符串,会调用引用类型的
toString
- 对于引用类型转成字符串,会调用引用类型的
-
函数就会得到一个函数体的代码字符串,而不是想要的函数引用
-
-
split:以逗号分隔每个元素来复原一个包含所有元素的数组
let arr = [1, [2, [3, 4]]];
function flatten(arr) {
return arr.toString().split(',').map(i=>Number(i));
}
console.log(flatten(arr)); // [1, 2, 3, 4]
正则 + JSON实现
-
在处理引用数据类型上也有局限性
-
注意元素是否是JSON的合法数据类型
let arr = [1, [2, [3, [4, 5]]], 6];
function flatten(arr) {
let str = JSON.stringify(arr);
str = str.replace(/(\[|\])/g, '');
// 拼接最外层,变成JSON能解析的格式
str = '[' + str + ']';
return JSON.parse(str);
}
console.log(flatten(arr)); // [1, 2, 3, 4,5]
Array.prototype.flat
Array.prototype.flat是ES6新增的一个数组方法
let arr = [1, [2, [3, 4]]];
function flatten(arr) {
return arr.flat(Infinity);
}
console.log(flatten(arr)); // [1, 2, 3, 4,5]