JavaScript 数组扁平化

61 阅读1分钟

普通递归实现

let arr = [1, [2, [3, 4, 5]]];
function flatten(arr) {
  let result = [];
  for(let i = 0; i < arr.length; i++) {
    // 当前元素是一个数组,对其进行递归展平
    if(Array.isArray(arr[i])) {
      // 递归展平结果拼接到结果数组
      result = result.concat(flatten(arr[i]));
    } 
    // 否则直接加入结果数组
    else {
      result.push(arr[i]);
    }
  }
  return result;
}
console.log(flatten(a));  //  [1, 2, 3, 4,5]

reduce实现

  • JS中的一个函数式编程API

  • reduce 的第一个参数用来返回最后累加的结果,第二个参数是当前遍历到的元素值

let arr = [1, [2, [3, 4]]];
function flatten(arr) {
    return arr.reduce(function(pre, cur){
        return pre.concat(Array.isArray(cur) ? flatten(cur) : cur)
    }, [])
}
console.log(flatten(arr));//  [1, 2, 3, 4,5]

扩展运算符实现

  • some,目的是判断当前数组是否还有数组元素

    • 有则对数组进行一层展开,同时将展开结果作为下一次判断的条件
let arr = [1, [2, [3, 4]]];
function flatten(arr) {
    while (arr.some(i => Array.isArray(i))) {
        arr = [].concat(...arr);
    }
    return arr;
}
console.log(flatten(arr)); //  [1, 2, 3, 4,5]

split + toString 实现

  • toStringObject原型链上的方法

    • JS中所有对象都派生自Object对象,都能调用toString

    • 数组的toString:将数组转换成一个元素间以逗号相隔的字符串

      • 它内部会先将数组展平成一维后再转换成字符串
    • toString过程中会发生类型转换

      • 对于引用类型转成字符串,会调用引用类型的toString
    • 函数就会得到一个函数体的代码字符串,而不是想要的函数引用

  • split:以逗号分隔每个元素来复原一个包含所有元素的数组

let arr = [1, [2, [3, 4]]];
function flatten(arr) {
    return arr.toString().split(',').map(i=>Number(i));
}
console.log(flatten(arr)); //  [1, 2, 3, 4]

正则 + JSON实现

  • 在处理引用数据类型上也有局限性

  • 注意元素是否是JSON的合法数据类型

let arr = [1, [2, [3, [4, 5]]], 6];
function flatten(arr) {
  let str = JSON.stringify(arr);
  str = str.replace(/(\[|\])/g, '');
  // 拼接最外层,变成JSON能解析的格式
  str = '[' + str + ']';
  return JSON.parse(str); 
}
console.log(flatten(arr)); //  [1, 2, 3, 4,5]

Array.prototype.flat

  • Array.prototype.flatES6新增的一个数组方法
let arr = [1, [2, [3, 4]]];
function flatten(arr) {
  return arr.flat(Infinity);
}
console.log(flatten(arr)); //  [1, 2, 3, 4,5]

链接:juejin.cn/post/699887…