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

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

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

递归核心思想

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

相关推荐
web_1553427465619 分钟前
性能巅峰对决:Rust vs C++ —— 速度、安全与权衡的艺术
c++·算法·rust
m0_7482382722 分钟前
项目升级Sass版本或升级Element Plus版本遇到的问题
前端·rust·sass
升讯威在线客服系统1 小时前
如何通过 Docker 在没有域名的情况下快速上线客服系统
java·运维·前端·python·docker·容器·.net
AsBefore麦小兜1 小时前
Vite vs Webpack
前端·webpack
LaughingZhu1 小时前
PH热榜 | 2025-02-23
前端·人工智能·经验分享·搜索引擎·产品运营
道不尽世间的沧桑3 小时前
第17篇:网络请求与Axios集成
开发语言·前端·javascript
diemeng11194 小时前
AI前端开发技能变革时代:效率与创新的新范式
前端·人工智能
bin91536 小时前
DeepSeek 助力 Vue 开发:打造丝滑的复制到剪贴板(Copy to Clipboard)
前端·javascript·vue.js·ecmascript·deepseek
计算机小白一个7 小时前
蓝桥杯 Java B 组之设计 LRU 缓存
java·算法·蓝桥杯
晴空万里藏片云7 小时前
elment Table多级表头固定列后,合计行错位显示问题解决
前端·javascript·vue.js