"数组扁平化"方法知多少
前言
在数据处理的场景中,经常需要处理多维数组,尤其是当数组内部嵌套了其他数组时,我们可能希望将这些嵌套的数组“展开”或“扁平化”为一维数组,以便进行后续的分析或操作。实现数字扁平化的方法有多种,下面,我将探讨几种常见的数字扁平化方法供小伙伴们参考!
flat()方法
flat()
方法是ES2019引入的数组扁平化方法,可以直接将所有值拼接到一个新数组中,把多维数组转化为一维数组。
代码示例:
const arr = [1, [2, [3, 4]]];
const flattened = arr.flat();
console.log(flattened); // [1, 2, 3, 4]
- 优点:简单、直接,无需额外编写逻辑。
- 缺点:性能可能不如手动实现的扁平化方法,特别是在处理大型数组和深度较大的数组时。
递归
递归是一种常见的实现数组扁平化的方法。其思路是通过递归遍历所有元素,如果遇到数组,则继续递归处理,直到将所有元素都放入一个新的一维数组中。具体实现方式有直接递归和reduce()方法两种。
直接递归
直接递归的实现方式是通过循环遍历数组元素,判断当前元素是否为数组,如果是,则递归调用扁平化函数,如果不是,则将其加入到新的一维数组中。
function flattenArray(arr) {
let result = [];
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
result = result.concat(flattenArray(arr[i]));
} else {
result.push(arr[i]);
}
}
return result;
}
const arr = [1, [2, [3, 4]]];
const flattened = flattenArray(arr);
console.log(flattened); // [1, 2, 3, 4]
- 优点:该方法兼容性好,适用于任意深度的多维数组。
- 缺点:可能会因为递归深度过大而导致栈溢出,特别是对于非常大的数组。
配合reduce()
reduce()
方法可以遍历数组的所有元素,并将它们合并到一个单独的值中。其语法如下:
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
其中,callback
参数是一个函数,用于处理数组的每个元素,accumulator
参数是一个累加器,用于存储上一次调用后的返回值,currentValue
参数是当前元素的值,index
参数(可选)是当前元素在数组中的索引,array
参数(可选)是原始数组。
在配合递归实现数组扁平化时,可以将reduce()
方法作为递归函数中的核心部分。每次递归时,都使用reduce()
方法来遍历当前层级的数组,如果当前元素为数组,则递归调用扁平化函数。
function flattenArray(arr) {
return arr.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenArray(val)) : acc.concat(val), []);
}
const arr = [1, [2, [3, 4]]];
const flattenedArr = flattenArray(arr); // [1, 2, 3, 4]
- 优点:使用了
reduce()
方法,使得代码更简洁。 - 缺点:性能可能不是最优的,因为和直接递归方法类似,都涉及到了递归和数组的连接操作。
解构
利用解构语法实现数组扁平化的思路是通过while循环遍历数组,并使用解构语法将第一个元素与剩余元素分离。如果分离后的第一个元素仍为数组,则使用解构语法继续分离,否则将其加入到新的一维数组中。
直接解构
function flatten(arr) {
const result = [];
while (arr.length) {
const [first, ...rest] = arr;
if (Array.isArray(first)) {
arr = [...first, ...rest];
} else {
result.push(first);
arr = rest;
}
}
return result;
}
const arr = [1, 2, [3, 4, [5, 6]]];
const flattenedArr = flatten(arr); // [1, 2, 3, 4, 5, 6]
配合some() + concat()
function flatten(arr) {
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr;
}
const arr = [1, 2, [3, 4, [5, 6]]];
const flattenedArr = flatten(arr); // [1, 2, 3, 4, 5, 6]
-
首先,函数接收一个数组作为输入参数,并将其赋值给变量
arr
。 -
使用
arr.some(item => Array.isArray(item))
判断数组arr
中是否存在任何一个元素是数组。Array.isArray(item)
用于检查当前元素item
是否为数组类型。 -
如果数组
arr
中存在元素是数组,则进入循环体。循环体内部执行以下操作:[].concat(...arr)
将数组arr
展开为一维数组。...arr
使用展开语法将数组arr
的每个元素作为单独的参数传递给concat
方法。[]
表示一个空数组,通过concat
方法将展开后的一维数组与空数组进行合并,得到新的扁平化后的数组。- 将新的扁平化后的数组赋值给变量
arr
,继续进行下一轮的循环。
-
如果数组
arr
中不存在任何元素是数组,则跳出循环。 -
返回最终的扁平化后的数组
arr
。
- 优点:使用解构语法来提高代码可读性。
- 缺点:同样存在对于特别大的多维数组可能会存在性能问题。
split() + toString()
const arr = [1, [2, [3, [4]], 5]];
const flattened = arr.toString().split(',').map(Number);
console.log(flattened); // [1, 2, 3, 4, 5] 注意:这里假设数组中的元素都是数字
- 首先,使用
toString()
方法将数组arr转换为字符串。这将得到字符串"1,2,3,4,5"。 - 接下来,使用
split(",")
方法将字符串按逗号分隔符进行拆分,得到一个字符串数组["1", "2", "3", "4", "5"]。 - 最后,通过map(Number)方法将字符串数组中的每个元素都转换为数字类型,得到扁平化后的数组
[1, 2, 3, 4, 5]
。
(仅适用于数组中的元素都是数字或可转换为字符串的情况)
- 优点:简单、直接,无需递归或循环。
- 缺点:仅适用于数组元素为数字或可转换为字符串的情况,且转换后的数组元素都是字符串类型,需要额外转换回原类型。性能可能不如其他方法,因为涉及到了字符串的转换和分割。
正则 + JSON
将数组转换为JSON字符串,然后使用正则表达式匹配到数组类型的字符串,再使用JSON.parse()方法将其转换回数组。
function flatten(arr) {
const str = JSON.stringify(arr);
const regex = /\[|\]/g;
const flattenedStr = str.replace(regex, '');
return JSON.parse(`[${flattenedStr}]`);
}
const arr = [1, 2, [3, 4, [5, 6]]];
const flattenedArr = flatten(arr); // [1, 2, 3, 4, 5, 6]
这种方法不是常见的扁平化方法,相比于其他方法可能更加复杂和低效。
结语
如果面试官问你还有什么方法可以让数组进行扁平化操作,每个小伙伴都能从容回答我还有....方法!
还有更多方法,欢迎评论区留言
转载自:https://juejin.cn/post/7371266185633792000