数组的扁平化:就是将一个嵌套多层的数组 array (嵌套可以是任何层数)转换为只有一层的数组
例如:假设有个名为 flatten 的函数可以做到数组扁平化, 效果就会如下:
实现数组扁平化的方法:
1、递归
- 判断数组内元素的类型;
- 如果是数组:对其递归扁平化,将其扁平化后的结果存到结果数组res中;
- 如果不是数组:直接存入新数组中。
function flatten(arr){
let res = [];
for(let i=0; i<arr.length; i++){
// 1. arr[i]是数组,通过递归对其扁平化
if(Array.isArray(arr[i])){
res = res.concat(flatten(arr[i]));
}else{
// 2. arr[i]不是数组,直接存入res
res.push(arr[i]);
}
}
return res;
}
输入
const arr = [1, [2, [3, 4, { a: 1 }], null], undefined];`
输出
[ 1, 2, 3, 4, { a: 1 }, null, undefined ]
2、reduce
2.1 reduce() 方法介绍
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
1)语法:
array.reduce(function(prev, current), initialValue)
- prev:函数传进来的初始值或上一次回调的返回值
- current:数组中当前处理的元素值
- initialValue:传给函数的初始值
2)例如:用reduce方法实现对数组的累加
reduce根据函数传进来的初始值,不断回调叠加最终算出数组的和
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const sum = arr.reduce(function (prev, current) {
prev.count = prev.count+current
return prev
}, {count: 0}) // 如果初始值为对象的话,返回的也是一个对象
console.log(sum) //{count: 55}
2.2 用reduce() 方法实现数组扁平化
function flatten(arr){
return arr.reduce((prev, next) => {
// prev:上一次操作的结果,即数组arr中已经扁平化的元素数组;
// next:当前处理的元素
return prev.concat(Array.isArray(next) ? flatten(next) : next);
}, []);//注意reduce的初始值应该是[],否则无法进行拼接
}
仔细对照方法一和方法二,两者思路完全一致——找到数据类型是数组的子元素,对其进行扁平化处理,只不过实现的细节略有不同。
prev相当于方法一中的结果数组res,存放当前已处理的数组元素
3、apply+some
既然方法二是方法一的变式,那个方法三也可以说是方法二的变式,但不采用递归的方式,而是一层一层“拆除”嵌套的方式
-
apply
:改变this指向的方法。调用函数 并 以一个数组(或类数组对象)的形式提供参数。
fn.apply(obj, [1, 2]); //调用函数fn,并传参数组[1,2],指定其this为obj
-
some
:测试数组中是不是至少有1个元素通过了被提供的函数测试。它返回的是一个Boolean类型的值
function flatten(arr){
while(arr.some( item => Array.isArray(item))){
//arr中至少有一个元素是数组,则执行下面操作
arr = [].concat.apply([],arr); //apply的主要目的就是减少括号
}
return arr;
}
其中:
arr = [].concat.apply([], arr);
// 等价于
[].concat(1, [2, [3, 4, { a: 1 }], null], undefined)
补充:apply的主要目的就是减少括号。执行一次,减少一层括号
例如:
4、ES6展开运算符
利用ES6的展开运算符精简方法三。唯一不同之处,将apply方法改为了展开运算符
function flatten(arr){
while(arr.some( item => Array.isArray(item))){
//arr中至少有一个元素是数组,则执行下面操作
arr = [].concat(...arr);
}
return arr;
}
5、toString
1)toString() 方法返回一个表示该对象的字符串
例:
2)实现数组扁平化
- 先将数组转化为字符串,再将其拆分为字符数组["1", "2", "3", "4", "1", "6", "7"]
- 再通过map,转化为 数字数组 [1, 2, 3, 4, 1, 6, 7]
function flatten(arr){
// arr.toString().split(',') 转化为字符串数组["1", "2", "3", "4", "1", "6", "7"]
return arr.toString().split(',').map(function(item){
return +item;
})
// 通过map操作之后,转化为[1, 2, 3, 4, 1, 6, 7]
}
存在问题:数据类型的转换存在限制,如果arr中有字符元素,扁平化后会异常