JS 数组扁平化手写:多种方法深度剖析与实现
在 JavaScript 编程中,数组扁平化是一个常见且实用的操作。所谓数组扁平化,就是将一个嵌套多层的数组转换为一个一维数组。例如,将 [1, [2, [3, 4]]] 转换为 [1, 2, 3, 4]。本文将详细介绍几种手写实现数组扁平化的方法,帮助你深入理解其原理和应用场景。
方法一:递归实现
递归是实现数组扁平化最直观的方法。其核心思想是遍历数组的每个元素,如果元素是数组,则递归调用扁平化函数处理该元素,否则将元素添加到结果数组中。
以下是递归实现数组扁平化的代码:
function flattenRecursive(arr) {
const result = []; // 初始化结果数组
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
// 如果元素是数组,递归调用 flattenRecursive 函数
result.push(...flattenRecursive(arr[i]));
} else {
// 如果元素不是数组,直接添加到结果数组
result.push(arr[i]);
}
}
return result;
}
const nestedArray = [1, [2, [3, 4]]];
const flattenedArray = flattenRecursive(nestedArray);
console.log(flattenedArray); // 输出: [1, 2, 3, 4]
在上述代码中,flattenRecursive 函数接受一个数组作为参数,通过 for 循环遍历数组的每个元素。如果元素是数组,则递归调用 flattenRecursive 函数,并使用扩展运算符 ... 将结果展开添加到 result 数组中;如果元素不是数组,则直接添加到 result 数组中。
方法二:使用 reduce 方法
Array.prototype.reduce 方法可以将一个数组的所有元素累加到一个单一的值或结果中。利用这个特性,我们可以使用 reduce 方法来实现数组扁平化。
以下是使用 reduce 方法实现数组扁平化的代码:
function flattenWithReduce(arr) {
return arr.reduce((acc, cur) => {
// 如果当前元素是数组,递归调用 flattenWithReduce 函数并展开结果
return acc.concat(Array.isArray(cur)? flattenWithReduce(cur) : cur);
}, []);
}
const nestedArray2 = [1, [2, [3, 4]]];
const flattenedArray2 = flattenWithReduce(nestedArray2);
console.log(flattenedArray2); // 输出: [1, 2, 3, 4]
在上述代码中,flattenWithReduce 函数使用 reduce 方法遍历数组的每个元素。acc 是累加器,初始值为一个空数组;cur 是当前元素。如果 cur 是数组,则递归调用 flattenWithReduce 函数并使用 concat 方法将结果合并到 acc 中;如果 cur 不是数组,则直接使用 concat 方法将其添加到 acc 中。
方法三:使用栈
栈是一种后进先出(LIFO)的数据结构。我们可以使用栈来实现数组扁平化,其基本思路是将数组的元素依次压入栈中,然后从栈中弹出元素进行处理。
以下是使用栈实现数组扁平化的代码:
function flattenWithStack(arr) {
const result = [];
const stack = [...arr]; // 复制数组到栈中
while (stack.length > 0) {
const current = stack.pop(); // 从栈中弹出一个元素
if (Array.isArray(current)) {
// 如果元素是数组,将数组的元素依次压入栈中
stack.push(...current);
} else {
// 如果元素不是数组,将其添加到结果数组的开头
result.unshift(current);
}
}
return result;
}
const nestedArray3 = [1, [2, [3, 4]]];
const flattenedArray3 = flattenWithStack(nestedArray3);
console.log(flattenedArray3); // 输出: [1, 2, 3, 4]
在上述代码中,flattenWithStack 函数首先将数组复制到栈中,然后使用 while 循环不断从栈中弹出元素进行处理。如果弹出的元素是数组,则将数组的元素依次压入栈中;如果弹出的元素不是数组,则将其添加到结果数组的开头。
方法四:指定扁平化深度
在实际应用中,我们可能只需要将数组扁平化到指定的深度,而不是完全扁平化。可以通过在递归函数中添加一个深度参数来实现指定扁平化深度的功能。
以下是实现指定扁平化深度的代码:
function flattenDepth(arr, depth = 1) {
const result = [];
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i]) && depth > 0) {
// 如果元素是数组且深度大于 0,递归调用 flattenDepth 函数并减少深度
result.push(...flattenDepth(arr[i], depth - 1));
} else {
// 如果元素不是数组或深度为 0,直接添加到结果数组
result.push(arr[i]);
}
}
return result;
}
const nestedArray4 = [1, [2, [3, 4]]];
const flattenedArray4 = flattenDepth(nestedArray4, 1);
console.log(flattenedArray4); // 输出: [1, 2, [3, 4]]
在上述代码中,flattenDepth 函数接受两个参数:arr 是要扁平化的数组,depth 是指定的扁平化深度,默认值为 1。在递归调用 flattenDepth 函数时,将深度减 1,直到深度为 0 时停止递归。
总结与建议
通过本文的介绍,我们学习了几种手写实现数组扁平化的方法,包括递归、使用 reduce 方法、使用栈以及指定扁平化深度。这些方法各有优缺点,在实际应用中可以根据具体需求选择合适的方法。
- 递归方法是最直观和容易理解的,但在处理深度嵌套的数组时可能会导致栈溢出。
reduce方法简洁高效,适合处理较小的数组。- 栈方法可以避免栈溢出问题,适用于处理深度嵌套的数组。
- 指定扁平化深度的方法可以满足只需要部分扁平化的需求。
在编写代码时,建议根据数组的大小和嵌套深度选择合适的方法,同时要注意处理边界情况,如空数组、深度为 0 等。通过掌握这些方法,你可以更好地处理 JavaScript 中的嵌套数组,提高代码的灵活性和可维护性。

