数组扁平化的8种方案

707 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

数组扁平化是一个多层嵌套的数组(多维数组)转换为只有一层的数组(一维数组)的过程。在面试过程中是一道高频热点题目,开发过程中也会偶尔使用的

现在有这么一个数组

const arr = [1, 2, [3, [4, 5]], 6, [7, 8]];

实现一个函数flatten将其扁平化

flat

直接调用 ES6 中的 flat 方法,可以直接实现数组扁平化,这是一个官方提供的API

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

使用方式:

var newArray = arr.flat([depth]);

depth: 指定要提取嵌套数组的结构深度,不指定时默认值为 1。指定为Infinity时则无论层都会扁平化为一层

arr.flat(Infinity)

⚠️:flat() 方法会移除数组中的空项

const arr = [1,,[3,4]];
arr.flat(Infinity); // [1, 3, 4]

普通递归

递归应该是最先想到的实现方式之一,递归总是可以朴实无华的解决很多问题😂

const flatten = (arr) => {
  let res = [];

  for (let i = 0; i < arr.length; i++) {
    const item = arr[i];
    if (Array.isArray(item)) {
      // 如果是数组
      res = res.concat(...flatten(item));
    } else {
      // 非数组 直接push
      res.push(item);
    }
  }

  return res;
};

上述就是通过循环递归的方式,一项一项地去遍历,如果每一项还是一个数组,那么就继续往下遍历,利用递归程序的方法,来实现数组的每一项的连接

递归 + reduce

使用reduce来替换普通递归中冗余的判断

const flatten = (arr) => {
  return arr.reduce((res, item) => {
    return Array.isArray(item) ? res.concat(...flatten(item)) : res.concat(item)
  }, []);
};

代码整体简洁很多,简化了for循环和if条件判断,但是整体思路和简单递归保持一致

while + some

const flatten = (arr) => {
  while (arr.some((item) => Array.isArray(item))) {
    arr = [].concat(...arr);
  }

  return arr;
};

整体思路:通过while进行不断循环,结束条件为整个数组变成一维数组,只要存在多维数组则循环条件就一直成立

some函数用于检测是否存在多维数组

while内部用于不断的一层一层扁平化数据

整个while循环结束,数组就是我们想要的一维数组

while + 堆栈

核心流程参考代码中注释

const flatten = (arr) => {
    const stack = [...arr];
    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();
};

toString + split

将数组toString

const str = arr.toString(); // 1,2,3,4,5,32,6,7,8

将得到的字符串split分割为数组,以,分割

str.split(','); // ['1', '2', '3', '4', '5', '32', '6', '7', '8']

简历的两个API便可以实现数组扁平化

Generator

利用Generator特性实现

const flatten = function* (arr) {
    for (const item of arr) {
        if (Array.isArray(item)) {
            yield* flatten(item);
        } else {
            yield item;
        }
    }
};

console.log([...flatten(arr)]);

Reg + JSON

const flatten = (arr) => {
  let str = JSON.stringify(arr);
  str = str.replace(/(\[|\])/g, '');
  str = '[' + str + ']';
  return JSON.parse(str); 
};

整体思路:

  1. 首先将数组序列化,得到一个字符串
  2. 利用正则将序列化后的字符串中的[]全部替换
  3. 手动拼接[],将其反序列化之后便是扁平化后的数组