扁平化数组是面试的热点问题
扁平化数组也就是将多维数组进行一个降维打击,其中递归是最好也是最容易想到的方法,下面先带大家认识下递归
递归核心思想
- 找规律
- 找出口
递归实现阶乘
比如我们来实现算阶乘
5! = 5 * 4 * 3 * 2 * 1
阶乘的规律就是当前值的阶乘永远等于当前值乘以前一位的阶乘
arduino
// mul(5) == 5 * mul(4)
// mul(4) == 4 * mul(3)
// mul(3) == 3 * mul(2)
// mul(2) == 2 * mul(1)
// mul(1) == 1
就这样如此循环下去,最终都会到1的阶乘,而1的阶乘就是等于1
scss
function mul(n){
if(n == 1){
return 1
}
return n * mul(n - 1)
}
console.log(mul(5)); // 120
也就是说假设我想要算出3的阶乘,我们这个函数就返回3 * 2!
,2的阶乘就会返回一个2 * 1!
,1的阶乘我们是清楚的啊。于是从1的阶乘返回到2的阶乘,2的阶乘返回到3的阶乘。
这个场景就有点像我让三楼大爷去拿一个钥匙,三楼大爷只知道二楼大爷清楚,于是跑到二楼,二楼大爷又只知道一楼大爷有,于是二楼大爷跑到一楼,一楼大爷才是真的清楚,将钥匙给到二楼大爷,于是二楼大爷跑回二楼将钥匙给到处在二楼的三楼大爷,三楼大爷才最终将钥匙给到我手上
阶乘的出口就是当n == 1
时,返回一个1出来
递归实现斐波那契
斐波那契数列:1 1 2 3 5 8 13 21......
也就是前两位相加等于后一位
递归的思想就是找规律和找出口,规律已经知道了,出口其实也很好找,就是当n == 1 || n == 2
返回 1
出来,相信你也可以实现
scss
function fb(n){
if(n == 1 || n ==2){
return 1
}
return fb(n - 1) + fb(n - 2)
}
console.log(fb(5)); // 5
回到今天的主题,递归如何实现扁平化数组呢?当中的规律是什么?
递归有时候很难!难在找规律!
扁平化数组
法一---flat
flat是es6之后打造出来天生服务于扁平化数组的方法,该方法按照一定的深度去遍历多维数组,并且返回一个新的数组
基本语法如下:
ini
var newArr = arr.flat(n)
- arr:即将扁平化的数组
- n:你需要降维的维度,默认为1
示例:
ini
var arr = [1, [2, [3, [4, 5]]]]
var newArr = arr.flat(3)
console.log(newArr) // [ 1, 2, 3, 4, 5 ]
上面的arr是个四维数组,因此你降三维即可,如果这里你降4维,5维会如何?
ini
var arr = [1, [2, [3, [4, 5]]]]
var newArr = arr.flat(5)
console.log(newArr) // [ 1, 2, 3, 4, 5 ]
降维降多了没有关系,永远都是到一维,所以当我们不清楚arr
是几维的时候,我们的参数可以直接放Infinity
Infinity
是个特殊的数值,表示无穷大,当我们输出1 / 0
的时候就会输出Infinity
法二---递归
css
var arr = [1, [2, [3, [4, 5]]]]
给到你这样一个多维数组,如何利用递归的思想进行降维呢?规律在哪里?
规律:是数组,外搬合并,不是数组,继续遍历
css
function flatten(arr) {
var result = []
for(var i = 0; i < arr.length ; i++){
if(arr[i] instanceof Array){
// flatten(arr[i])递归得到的数组要进行合并
// result.push(flatten(arr[i])) push会把整个第二层的数组放进去,没用
// a.concat(b) || [].concat(a,b)
var nextArr = flatten(arr[i])
result = result.concat(nextArr)
// concat返回新数组
}else{
result.push(arr[i])
}
}
return result
}
console.log(flatten(arr)); // [ 1, 2, 3, 4, 5 ]
这里判断是否是数组可以也可也用Array.isArray(arr)
,如果是数组,就递归,将这个数组放进函数里面,如果不是数组,直接push到空数组中即可
扁平n维
ini
const flattening = (arr, n) => {
for(var i = 0; i<arr.length; i++){
if(Array.isArray(arr[i]) && n > 0){
nextArr = flattening(arr[i], n - 1)
}else{
res.push(arr[i])
}
}
}
法三---reduce版递归
reduce方法是数组对象的一个高阶函数,类似map,接受一个回调函数,这个函数可以做一个累计操作,reduce返回一个最终值。
所谓回调,指的是执行完后执行另一个操作,用于处理异步
reduce做累加:
javascript
var arr = [1, 2, 3, 4, 5]
var sum = arr.reduce(function(pre,item,index,arr){
return pre + item
},0)
console.log(sum) // 15
其中:
- pre:上一次回调的返回值
- item:当前元素的值
- index:当前元素的下标
- arr:调用reduce的数组
- 0:pre的初始值
因此这里我们用reduce扁平化数组,pre的初始值就是个空数组,如果当前的item是数组,那就直接把对他进行遍历,如下:
javascript
var arr = [1, [2, [3, [4, 5]]]]
function flatten(arr){
return arr.reduce(function(pre, item){
return pre.concat(Array.isArray(item) ? flatten(item) : item)
}, [])
}
console.log(flatten(arr)) // [ 1, 2, 3, 4, 5 ]
如果觉得本文对你有帮助的话,可以给个免费的赞吗[doge] 还有可以给我的gitee链接codeSpace: 记录coding中的点点滴滴 (gitee.com)点一个免费的star吗[星星眼]