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

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

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

递归核心思想

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

相关推荐
腾讯TNTWeb前端团队32 分钟前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰4 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪4 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪4 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy5 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom5 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom6 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom6 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom6 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom6 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试