前言
想要解出一道题目,你只用会一种方法就够了,但是如果你会n种方法,那么你就会让人高看一眼。今天我们就要在这里一起探讨下数组扁平化的方法。
什么是数组扁平化?
扁平化是我们对数组常用的一种操作,其目的是将一个多维度的数组转换为一个单一的一维数组。在多维数组中,元素可以是其他数组,从而形成嵌套结构。扁平化过程就是遍历这样的数组结构,如果遇到子数组,则将其内容直接提取出来放入结果数组中,直到所有的嵌套结构都被展平,最终得到一个没有嵌套的、只包含原始数据项的一维数组。例如,将[1,[2,[3,4,[5,[6]]]]]这个数组扁平化后,我们将得到[ 1, 2, 3, 4, 5, 6 ]这样一个数组。
数组扁平化的方法
利用递归的方法
我们一般碰到这种多维度的数组,通常使用递归的方法逐层平铺开来。即我们设置一个方法对这种数组进行遍历,添加到我们的新数组中,如果遍历得到元素的还是数组将继续调用此方法进行遍历,直到不是数组才停止下一层的遍历。就和剥洋葱一样,当我们剥到后一层的时候,就不再剥了。
具体实现:
function flatten(arr) {
let result = [];
for (let i = 0,len = arr.length; i < arr.length;i++){
if(Array.isArray(arr[i])){
result = result.concat(flatten(arr[i]))
}else{
result.push(arr[i])
}
}
return result;
}
其中let i = 0,len = arr.length; i < arr.length;i++设置一个变量来存储arr.length,可以提高循环的效率。因为我们循环时每次都要计算数组的长度,设置变量存储后我们只用计算一次,这样就可以减少相应的时间,从而达到提高效率的目的。
result = result.concat(flatten(arr[i]))是用来将数组result和递归后的数组连接组成一个新数组。
递归虽然在解决数组扁平化的问题上非常有用,但是递归的缺点还是挺明显的。
- 首先就是性能开销较大: 递归由于涉及到更多的函数调用,会有额外的时间和空间开销。每次函数调用都需要保存上下文,分配和释放内存空间,这些操作都会影响程序的运行效率。
- 其次就是递归对于一些不熟悉的人来说就比较难理解:递归逻辑往往比较抽象,需要清晰地理解递归终止条件和递归表达式,否则容易出错。
利用toString方法
toString方法是将数组的内容转换为字符串,不管多少层的数组都可以。例如,
通过toString这个特性,我们就应该有所想法了吧。我们将一个n维度的数组转换成一个字符串,然后通过,来分割它得到一个字符数组,最后遍历并进行类型转换存入一个新的数组。
在这里,我们进行类型转换也有好几种方法。
- parseInt方法,将字符串转换为整数
- Number强制类型转换 显示类型转换
- 使用
+进行隐式类型转换 - 使用map方法
补充说明:
-
我们都知道
+的作用,一是连接字符串,二是进行数值计算,而我们不知道的是它其实还可以转化成数字。当它放在一个变量或表达式的前面时,起到了将该值转换为数字类型的作用。如果该值可以被解释为一个数字(比如字符串 "123"),它会被转换成对应的数字类型(123)。如果该值无法转换为数字(比如字符串 "abc"),则结果将是NaN(Not-a-Number)。 -
map() 是 JavaScript 数组的一个内置函数方法,用于对数组中的每个元素执行一个指定的函数,并返回一个新的数组。它不会修改原始数组,而是返回一个新的数组,新数组的元素是回调函数的返回值。
具体的使用请看下面的代码:
function flatten(arr){
var strArr = arr.toString();
var numArr = strArr.split(',');
var result = []
for(var i = 0,len = numArr.length; i < len; i++){
// result.push(Number(numArr[i]))
result.push(parseInt(numArr[i]))
//result.push(+numArr[i]) //+
}
return result;
}
function flatten(arr) {
return arr.toString().split(',').map(function(item){
return +item
})
}
利用内置flat()方法
flat() 方法是 JavaScript 中数组的一个内置方法,用于将多维数组扁平化,即把嵌套的数组拉平为一维数组。这个方法是在 ES2019(ECMAScript 2019)标准中引入的,为处理多维数组提供了一种简洁的解决方案。他接受一个参数表示扁平化的深度,默认为 1,意味着只会扁平化一层嵌套的数组。如果提供更大的数字,flat() 会深入更深层次的嵌套进行扁平化。例如:
let arr = [1, [2, [3, 4], 5], 6];
let flatArr = arr.flat();
console.log(flatArr); // 输出: [1, 2, [3, 4], 5, 6]
因为它默认就是1,所以只展开一层的。[3, 4] 这个子数组没有被进一步扁平化。
对于极端复杂的嵌套结构,或者不确定嵌套深度的情况,可以使用 Infinity 作为 depth 参数,这样可以确保所有级别的嵌套都被扁平化。就例如我们这里的数组[1,[2,[3,4,[5,[6]]]]]我们就可以使用Infinity作为参数。
let arr = [1,[2,[3,4,[5,[6]]]]];
let flatArr = arr.flat();
console.log(flatArr); // 输出: [1, 2, 3, 4, 5, 6]
小结
我在这里就只提到这些方法,虽然没有标题说的那么夸张,但是可见扁平化的方法还是挺多的,一千个人就有一千个哈姆雷特,条条大路通罗马。我相信,各位大佬们肯定还有许多的方法实现数组的扁平化,大佬可以分享一下哟,说不好最后还真的有一千种解法呢!