前言
在面试中我们常常会被问到数组的扁平化,把多维数组降维被称为扁平化。在这过程中我们会使用到递归,接下来我们来好好聊聊。
递归
首先我们先来看一个例子,数字的阶乘
function mul(num){
let res=1;
for(let i=1;i<=num;i++){
res=res*i;
}
return res;
}
let a=mul(5);
console.log(a);
这里我们使用了for循环,从1开始不断相乘直到i等于num,而这里我们就可以引入递归的思想,递归说白了就是自己调用自己,还是这个题目我们可以这么想:
mul(5)=5*mul(4);
mul(4)=4*mul(3);
mul(3)=3*mul(2);
mul(2)=2*mul(1);
mul(1)=1
递归思想最重要就是两点:1.找公式 2.找出口
公式就是mul(num)=mun*mul(num-1),而出口就是当num=1或者0的时候
function mul(num){
if(num==1 || num==0){
return 1;
}else{
return num*mul(num-1);
}
}
console.log(mul(5));//120
接下来我们看另一个例子,斐波那契数列
斐波那契数列:1,1,2,3,5,8,13,21.....除了第一位和第二位,后一位数为前两位之和
因此公式为fb(n)=fb(n-1)+fb(n-2) (n>2)
出口就为n=1或n=2
代码如下:
function fb(n){
if(n==1 || n==2){
return 1;
}else{
return fb(n-1)+fb(n-2)
}
}
数组扁平化
在面试中扁平化是一个高频考点,接下来我们聊聊一些扁平化的方法
方法一: flat()
flat()是js自带的一种方法,专门解决数组扁平化的问题
const arr=[1,2,[3,4,[5]]]
const newarr=arr.flat()
console.log(newarr);//[1, 2, 3, 4, [5]]
其中flat()里的值默认为1,代表降一次维,填2就降两次维,但在实际应用时我们可能不知道数组到底有几维想把它降成一维时,一般使用flat(Infinity),无限大,无限小就是flat(-Infinity)
方法二:递归
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);//[ 1, 2, 3, 4, 5 ]
这里我们先创造一个空数组,通过Array.isArray(arr[i])判断子元素是否是数组,如果不是则将元素放入空数组,是则进行递归,再创造一个新的空数组,进行判断放值,在最里层的循环结束再将数组return出来,和上一层的数组用concat拼接,最后return出这个数组
concat()可以将两个数组拼接起来
let arr=[1,2]
let arr2=[3,4]
let allArr=arr.concat(arr2)//[1,2,3,4]
//也可以 let allarr=[...arr,...arr2]
方法三:toString()
逻辑:toString可以将数组转换为字符串,再用splict()将字符串变为数组,最后使用map遍历数组
toString是一个神奇的方法,不管你是几维数组,它都可以变成字符串,如:
const arr=[1,2,[3,4,[5]]]
let str=arr.toString()
console.log(str);
split()里面写什么就以什么分割字符串
完整代码如下:
const arr=[1,2,[3,4,[5]]]
let str=arr.toString()//split()里面写什么就以什么分割字符串
const newarr=str.split(',').map((item)=>{//map()遍历数组,返回一个新数组
return Number(item)
})
console.log(newarr);
return Number(item)将数组里的字符串变为num类型,这个方法有一点需要注意,就是数组里不能出现非数字类型的元素,否则就会出现NaN(NaN也是数字类型,代表not a number)
方法四:reduce()
reduce()中要放两个参数,如:
arr.reduce(function(pre,item,index,arr){},initalValue)
let arr=[1,2,3,4,5,6,7]
let sum=arr.reduce(function(pre,item,index,arr){
return pre+item//第一次是0+1,第二次是1+2.。。。。
},0)//reduce用于累计,第二个参数是初始值
console.log(sum)//28
这里的代码中初始值为0,所以第一次return出0+1=1,1就变成了第二次的初始值,所以第二次return出1+2=3......如此重复,所以最后的sum为28
用reduce实现扁平化如下:
const arr=[1,2,[3,4,[5]]]
function flatten(arr){
return arr.reduce((pre,item)=>{
return pre.concat(Array.isArray(item)?flatten(item):item)
},[])
}
console.log(flatten(arr));
这里的初始值是一个空数组,利用三元运算符判断arr中的元素是否是数组,如果不是则通过concat拼接到空数组中,如果是则将数组元素递归,再次创建空数组,再次进行判定。当内部全部判断结束,将数组返回上一层进行拼接
方法五:some
数组中的some可以判断数组中是否存在某个值,并且返回布尔类型(true or false)
具体代码如下:
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】】
}
return arr
}
console.log(flatten(arr))
...arr是解构,将arr的每一项解构返回出来,...arr结果为1,2,[3,4,[5]]
arr=[].concat(...arr)的结果为[1,2,3,4,[5]],主要数组中还存在数组元素,arr.some(item=>Array.isArray(item))就为true,while就会循环,进行降维
结语
今天我们聊了递归思想和数组扁平化的几个方法,希望在你看完这篇文章之后面对hr的“刁难”可以多几分从容和自信,华丽的拿下,好好学习,天天向上。