前言
当一个数组多维时,怎么将其变成一维,从而实现数组扁平化呢?实现数组扁平化的方法有多种,接下来通过一些代码实例来介绍五种方法。拿下面试官!
正文
递归
概念:在一个函数中直接或间接地调用自身的方式
实现阶乘
阶乘n!=n*(n-1)*(n-2)...1,即n!=n(n-1)!,所有可以通过递归的方式来实现。
代码实现:
scss
function mul(n) {
if (n === 1) {
return 1;
}
return n * mul(n - 1);
}
实现斐波拉契数列
斐波拉契数列:1 1 2 3 5 8 13 21 34...
观察上面的数列可以发现它们之间的关系为fb(n - 1) + fb(n - 2)=fb(n),所以可以通过递归的方式来实现。
代码实现:
scss
function fb(n) {
if (n === 1 || n === 2) {
return 1;
}
return fb(n - 1) + fb(n - 2);
}
给出数组arr = [1, 2, [3, 4, [5]]],实现将数组扁平化,以下为实现的五种方法:
数组自带的flat()方法
ini
const arr = [1, 2, [3, 4, [5]]];
const newArr = arr.flat(Infinity);
console.log(newArr);
递归的方法
插播!先介绍一下关于concat()的方法和解构的概念
concat():
用于将一个或多个数组连接返回形成的一个新数组,原数组不会发生改变。
两个数组的连接:
ini
let arr = [1, 2]
let arr2 = [3, 4]
let allArr = arr.concat(arr2);
console.log(allArr, arr);
三个数组的连接:
ini
let arr = [1, 2]
let arr2 = [3, 4]
let arr3 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
let allArr = arr.concat(arr2, arr3);
console.log(allArr, arr);
上面的allArr = arr.concat(arr2, arr3);
还可以写成 allArr = arr.concat(arr2).concat(arr3);
解构
通过解构将数组的元素直接分配给变量,...x
将剩下所有的值分给该变量,如果有多个,则以数组的形式赋值给该变量,解构只能一层一层解。
ini
let arr3 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
let [a, b, ...c] = arr3;
console.log(a, b, c);
所以连接两个数组也可以通过解构和数组的方式来实现,对两个数组进行解构,然后放在一个数组中
ini
let arr = [1, 2]
let arr2 = [3, 4]
let allArr = [...arr, ...arr2];
console.log(allArr, arr);
通过for循环遍历数组,如果遍历到非数组则将其push到新建的·数组res中,反之,则采用递归的方式再次遍历该数组,并将再次遍历到的结果与第一次遍历的res数组连接起来,因为遍历三次得到的res分别为[1,2]、[3,4]、[5]
,所以每次递归再次调用该函数时都要将res与下一次的结果连接起来,才能得到[1,2,3,4,5]
,下面使用两种方法来实现连接
使用concat方法
ini
const arr = [1, 2, [3, 4, [5]]];
function flatten(arr) {
let res = [];
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
res = res.concat( flatten(arr[i]));
}
else{
res.push(arr[i]);
}
}
return res;
}
const newArr = flatten(arr);
console.log(newArr);
使用解构方法
ini
const arr = [1, 2, [3, 4, [5]]];
function flatten(arr) {
let res = [];
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
res = [...res, ...flatten(arr[i])];
}
else{
res.push(arr[i]);
}
}
return res;
}
const newArr = flatten(arr);
console.log(newArr);
toString() + split()的方法
- 先将数组通过toString()方法转换为字符串
'1','2'',3','4','5'
- 通过split方法以逗号为分隔符将上面的字符串变为数组
['1','2'',3','4','5']
- 通过map遍历该数组,并将数组内的元素转为number类型,结果为
[1,2,3,4,5]
ini
const arr = [1, 2, 3, [4, [5]] ];
let str = arr.toString();
const newArr = str.split(',').map((item) => {
return Number(item);
});
console.log(newArr);
但是! toString方法有缺陷,只能处理数组中只有数字类型的情况
reduce()+concat的方法 -- 递归
javascript
array.reduce(callbackFn(pre, item, index, arr){}, initialValue])
callbackFn
:回调函数,包含四个参数:pre
:累计器累存回调的返回值;它是上一次调用回调时返回的累积值,或者是初始值(initialValue)。item
:数组中当前被处理的元素。index
(可选):当前元素在数组中的索引。默认值:从0开始。arr
(可选):调用了reduce()
方法的数组本身。initialValue
(可选):作为第一次调用callbackFn
函数时pre
的值。如果省略,则pre
的初始值为数组的第一个元素,item
从第二个元素开始。 通过reduce遍历该数组,pre为上一次reduce的结果,所以pre+item可以实现将所有的数组中的值相加起来,initialValue为0,即pre初始为0,pre+item-->0+1 1+2 3+3 6+4 10+5 15+6 21+7
,所以结果为28
ini
const arr = [1, 2, 3, 4, 5, 6, 7];
let sum = arr.reduce(function(pre, item, index, arr) { // 上一次reduce的执行结果
return pre + item;
}, 0)
console.log(sum);
通过reduce遍历该数组,将initialValue初始值为一个空数组,所以pre初始值为[],先判断遍历到的item是否为数组,如果为数组就进行递归,不是则为原来的item,然后将pre和递归返回的结果或者item通过concat连接起来,再将其返回。
javascript
const arr = [1, 2, [3, 4, [5]] ];
function flatten(arr) {
return arr.reduce((pre, item) => {
return pre.concat(Array.isArray(item) ? flatten(item) : item); // [1, 2] [3, 4] [5]
}, [])
}
console.log(flatten(arr));
some+解构+concat的方法
some():用于检测数组中的元素是否符合条件,数组中的至少有一个元素符合条件,符合返回true,否则,则返回false
c
array.some(callbackFn(element, index, array){}, thisArg)
callbackFn
:测试数组中每个元素的函数。该函数接收三个参数:element
:当前遍历的元素。index
(可选):当前元素的索引。array
(可选):调用some()
的数组本身。thisArg
(可选):执行回调函数callbackFn
时this
被指向的对象。
javascript
let arr4 = [1, 2, 3, 4, 5, 6, 7]
let res = arr4.some((item) => {
return item > 5
})
console.log(res);
通过some判断数组中是否有数组,如果有则通过concat和解构结合的方法将其先解构再连接起来,数组先变成[1,2,3,4,[5]]
,然后变成[1,2,3,4,5]
,得出最终结果。
ini
const arr = [1, 2, [3, 4, [5]] ];
function flatten(arr) {
while (arr.some(item => Array.isArray(item))){
arr = [].concat(...arr); // [1, 2, 3, 4, [5]] --> [ 1, 2, 3, 4, 5 ]
}
return arr;
}
console.log(flatten(arr));
结语
如果你将这五种方法淡定的说出来,面试官一定被你拿下!嘿嘿~如果还有其他的方法的话,希望可以得到你们的分享哦,大家一起好好学习,天天向上!