js 数组扁平化的7种方法

113 阅读2分钟

日常的开发种,数组的扁平化还是很重要的,比如更容易潜复制啥的!

1 简单的递归实现

这边主要还是利用递归,循环遍历数组,如果下一个是数组则进入flatten1递归,如果不是则直接推入result。

function flatten1(arr) {
  let result = [];
  for (let i = 0; i < arr.length; i++) {
    if (Array.isArray(arr[i])) {
      result = result.concat(
        flatten1(
          // 如果还是数组, 此处为递归的关键代码
          arr[i]
        )
      );
    } else {
      result.push(arr[i]);
    }
  }
  // 返回的这个与concat合并
  return result;
}
console.log(flatten1([2, [3, [4, 5, 6]]]));

2 使用reduce实现的递归方式(基本原理和1相似)

采用reduce实现的方式和1差不错,只不过将for循环变成了reduce而已。

function flatten2(arr) {
  return arr.reduce((prev, next) => {
    // 关键代码
    return prev.concat(Array.isArray(next) ? flatten2(next) : next);
  }, []);
}
console.log(flatten2([2, [3, [4, 5, 6]]]));

3 纯粹使用[].concat() 进行合并的办法

直接用some进行推入,减少了递归的调用,一般来说能不用递归的性能都会好很多。

function flatten3(arr) {
  while (
    arr.some((item) => {
      return Array.isArray(item); // 返回布尔值
    })
  ) {
    // 可以打平数组
    arr = [].concat(...arr);
  }
  return arr;
}
console.log(flatten3([1, 2, 3, [4, 5, 6, [7, 8, 9]]]));

4.split和toString共同处理

此采用了取巧的办法,直接用toString进行打平,然后用","进行分割,最后利用map对数组进行包装(其实是将每一项的字符串转换为数组而已)。

function flatten4(arr) {
  return arr
    .toString()
    .split(',')
    .map((item) => Number(item));
}
console.log(flatten4([1, 2, 3, [4, 5, 6, [7, 8, 9]]]));

5.ES6的flat的办法

这里的代码是最简单的,直接利用es6的语法,然后通过Infinity的方式进行深层次的解析,直到最后每一项没有数组嵌套为止。

function flatten5(arr) {
  return arr.flat(Infinity);
}
console.log(flatten5([1, 2, 3, [4, 5, 6, [7, 8, 9]]]));

6.正则和JSON方法共同处理

采用正则表达式,其中就是说,匹配到[或者是]就给它置为空,最后少了的[]补全就行了。

function flatten6(arr) {
  let str = JSON.stringify(arr);
  str = str.replace(/(\[|\])/g, '');
  str = '[' + str + ']';
  return JSON.parse(str);
}
console.log(flatten6([1, 2, 3, [4, 5, 6, [7, 8, 9]]]));

7.堆栈方法(个人觉得这个方法不错)

这种办法采用堆栈的办法,就是从数组的末尾取出来判断此项是否为数组,如果是数组则打平再push到原来的栈中去,如果不是数组则从索引(length - 1)开始一个个push到新的数组中去。当最后全部完成后将数组反转即可。

function flatten7(arr) {
  const stack = [...arr];
  const res = [];
  while (stack.length) {
    // 使用pop从stack中取出并移除值,直到没有为止
    const next = stack.pop();
    if (Array.isArray(next)) {
      // 使用push送回内层数组中的元素,不会改动原始输入 original input
      stack.push(...next);
    } else {
      res.push(next);
    }
  }
  // 使用reverse恢复数组的顺序
  return res.reverse();
}
console.log(flatten7([1, 2, 3, [4, 5, 6, [7, 8, 9]]]));堆栈方法(个人觉得这个方法不错)