前端面试题——数组扁平化(递归、迭代&generator)

前端面试,五花八门。最近我又看到了一道题——数组扁平化。

  • 对于多层嵌套数组:[1, [2, [3, 4, [5]]]],要求转换为只有一层的数组:[1, 2, 3, 4, 5]

那么数组的扁平化究竟怎么实现呢?这篇文章介绍递归、迭代、generator三种方法。

递归

看到这道题目,最最直接的反应就是递归了:对于每个子元素,如果是数组的话,就递归调用这个子元素。先看代码:

function flatten(arr) {
    if (!Array.isArray(arr)) {
        return [arr];
    }
    let res = [];
    for (let i=0;i<arr.length;i++) {
        res.push(...flatten(arr[i]));
   }
   return res;
}

const arr = [1, [2, [3, 4, [5]]]];
console.log(flatten(arr))

写递归分三步:

  1. 第一步:确定结束条件。在这个问题中,如果当前传入的元素arr不是数组的话,就包装成数组返回。如果是数组的话,才继续进行接下来的步骤。
  2. 第二步:对于每个子元素进行处理。我们创建一个叫做res的数组,对于每个子元素,都把它放进数组当中。而每个子元素都可能是数组,这里我们不需要判断子元素是不是数组,因为在结束条件中会自动判断。
  3. 第三步:返回值。这里只要返回res就可以。

运行程序,输出结果:[1, 2, 3, 4, 5]

迭代

对于把递归转换成迭代,很多情况下都需要一个stack来模拟函数调用。先看代码:

function flatten2(arr) {
  const stack = [...arr];
  const res = [];
  while (stack.length) {
    // 从栈里取出
    const next = stack.pop();
    if (Array.isArray(next)) {
      // 把next扁平化,然后放入stack中
      stack.push(...next);
    } else {
      res.push(next);
    }
  }
  // reverse to restore input order
  return res.reverse();
}

console.log(flatten2(arr))

基本思想就是,先把arr中的东西都放入stack中,然后不停pop stack中的东西。如果pop出来的是一个数组,那么把数组扁平化,再放入stack中;如果pop出来的不是数组,那么放入res中。

运行程序,输出结果:[1, 2, 3, 4, 5]

generator

generator是ES6提供的一种异步编程解决方法。这里的generator方法的思想也是迭代的(当然前面我迭代的代码,可以把判断是否是array的条件放在if条件当中)

function* flatten3(arr) {
    let length = arr.length;
    for (let i=0; i<length; i++) {
        let item = arr[i];
        if (Array.isArray(item)) {
    	    yield* flatten3(item);
        } else {
    	    yield item;
        }
    }
} 

let res = [];
for (let f of flatten3 (arr)) {
    res.push(f);
}
console.log(res)

需要注意的是,调用flatten3 (arr)并不会直接得到结果,需要时用next()或者放在for循环中得到所有结果。

好啦,这就是数组扁平化的几种方法。希望大家面试一切顺利!顺便关注我的公众号:前端三剑客

weixin.qq.com/r/CjsyKv3 (二维码自动识别)

发布于 2020-01-27 19:37