递归详解---扁平化数组常用方法

扁平化数组是面试的热点问题

扁平化数组也就是将多维数组进行一个降维打击,其中递归是最好也是最容易想到的方法,下面先带大家认识下递归

递归核心思想

  1. 找规律
  2. 找出口

递归实现阶乘

比如我们来实现算阶乘

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吗[星星眼]

相关推荐
Martin -Tang20 分钟前
vite和webpack的区别
前端·webpack·node.js·vite
迷途小码农零零发21 分钟前
解锁微前端的优秀库
前端
王解1 小时前
webpack loader全解析,从入门到精通(10)
前端·webpack·node.js
老码沉思录1 小时前
写给初学者的React Native 全栈开发实战班
javascript·react native·react.js
我不当帕鲁谁当帕鲁1 小时前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段
前端·javascript·arcgis
那一抹阳光多灿烂1 小时前
工程化实战内功修炼测试题
前端·javascript
爱吃生蚝的于勒1 小时前
C语言内存函数
c语言·开发语言·数据结构·c++·学习·算法
放逐者-保持本心,方可放逐2 小时前
微信小程序=》基础=》常见问题=》性能总结
前端·微信小程序·小程序·前端框架
毋若成4 小时前
前端三大组件之CSS,三大选择器,游戏网页仿写
前端·css
红中马喽4 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习