数组多维转一维度(扁平化)的6种方法

2,831 阅读3分钟

数组扁平化

  • flat()
  • 使用 reduce 与 concat
  • 使用扩展运算符
  • 使用forEach
  • 使用堆栈stack
  • 使用 Generator 函数

① flat()

MDN释义:flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。

语法:var newArray = arr.flat([depth]) depth 默认为 1

举个例子🌰

var arr1 = [1, 2, [3, 4]];
arr1.flat(); 
// [1, 2, 3, 4]

var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]

var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]

如果不知道数组是多少维度,可以传 Infinity 来展开任意深度的嵌套数组

var arr = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

② 使用 reduce 与 concat

reduce

reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。

reduce 资料

基本用法: const total = [1, 2, 3].reduce((acc, cur) => acc + cur, 1); // 6

concat

concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。concat() 也适用于字符串。

concat 资料

基本用法: var arr = [1, 2, 3].concat([4, 5]); // [1, 2, 3, 4, 5]

举个例子🌰

// 二维
const arr = [1, 2, [3, 4]];
arr.reduce((acc, cur) => acc.concat(cur), [])
// [1, 2, 3, 4]

// 三维及以上可以使用递归
function flatArr(arr, dep = 1) {
  if (dep > 0) {
    return arr.reduce(
      (acc, cur) =>
        acc.concat(Array.isArray(cur) ? flatArr(cur, dep - 1) : cur),
      []
    );
  } else {
    return arr;
  }
}
flatArr([1, 2, [3, 4, [5, 6]]], 3);
// [1, 2, 3, 4, 5, 6]

// 不知道数组维度,可以传 Infinity
flatArr([1, 2, [3, 4, [5, 6]]], Infinity);
// [1, 2, 3, 4, 5, 6]

③ 使用扩展运算符 ...

扩展运算符是什么不用多说了了吧!

目前只想到能处理二维数组

举个例子🌰

// 二维
const arr = [1, 2, [3, 4]];
var newArr = [].concat(...arr);
// [1, 2, 3, 4]

// 三维待补充

④ 使用forEach

forEach() 方法对数组的每个元素执行一次给定的函数。

forEach资料

基本用法: arr.forEach(((item, index) => item))

举个例子🌰

// 二维及以上维度
const newArr = []; // 全局变量或者闭包也可以

function flatArr(arr, dep = 1) {
  arr.forEach(ele => {
    if(Array.isArray(ele) && dep > 0) {
      flatArr(ele, dep - 1);
    } else {
      newArr.push(ele);
    }
  });
  return newArr;
}

flatArr([1, 2, [3, 4, [5, 6]]], 3);
// [1, 2, 3, 4, 5, 6]

⑤ 使用堆栈stack

以下为MDN示例🌰

// 无递归数组扁平化,使用堆栈
// 注意:深度的控制比较低效,因为需要检查每一个值的深度
// 也可能在 shift / unshift 上进行 w/o 反转,但是末端的数组 OPs 更快
var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]];
function flatten(input) {
  const stack = [...input];
  const res = [];
  while (stack.length) {
    // 使用 pop 从 stack 中取出并移除值
    const next = stack.pop();
    if (Array.isArray(next)) {
      // 使用 push 送回内层数组中的元素,不会改动原始输入
      stack.push(...next);
    } else {
      res.push(next);
    }
  }
  // 反转恢复原数组的顺序
  return res.reverse();
}
flatten(arr1);// [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
// 递归版本的反嵌套
function flatten(array) {
  var flattend = [];
  (function flat(array) {
    array.forEach(function(el) {
      if (Array.isArray(el)) flat(el);
      else flattend.push(el);
    });
  })(array);
  return flattend;
}

⑥ 使用 Generator 函数

Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。

Generator 资料

举个例子🌰

function* flatArr(array) {
  for (const item of array) {
      if (Array.isArray(item)) {
          yield* flatArr(item);
      } else {
          yield item;
      }
  }
}

const arr = [1, 2, [3, 4, [5, 6]]];
const flattened = [...flatArr(arr)];
// [1, 2, 3, 4, 5, 6]

写在后面

总结不易,麻烦您给👴点个赞👍