likes
comments
collection
share

"数组扁平化"方法知多少

作者站长头像
站长
· 阅读数 55

前言

在数据处理的场景中,经常需要处理多维数组,尤其是当数组内部嵌套了其他数组时,我们可能希望将这些嵌套的数组“展开”或“扁平化”为一维数组,以便进行后续的分析或操作。实现数字扁平化的方法有多种,下面,我将探讨几种常见的数字扁平化方法供小伙伴们参考!

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]
  1. 首先,函数接收一个数组作为输入参数,并将其赋值给变量arr

  2. 使用arr.some(item => Array.isArray(item))判断数组arr中是否存在任何一个元素是数组。Array.isArray(item)用于检查当前元素item是否为数组类型。

  3. 如果数组arr中存在元素是数组,则进入循环体。循环体内部执行以下操作:

    • [].concat(...arr)将数组arr展开为一维数组。...arr使用展开语法将数组arr的每个元素作为单独的参数传递给concat方法。
    • []表示一个空数组,通过concat方法将展开后的一维数组与空数组进行合并,得到新的扁平化后的数组。
    • 将新的扁平化后的数组赋值给变量arr,继续进行下一轮的循环。
  4. 如果数组arr中不存在任何元素是数组,则跳出循环。

  5. 返回最终的扁平化后的数组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] 注意:这里假设数组中的元素都是数字
  1. 首先,使用toString()方法将数组arr转换为字符串。这将得到字符串"1,2,3,4,5"。
  2. 接下来,使用split(",")方法将字符串按逗号分隔符进行拆分,得到一个字符串数组["1", "2", "3", "4", "5"]。
  3. 最后,通过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
评论
请登录