🌟秒杀!数组扁平化(Flatten)!前端常见手写题!

377 阅读5分钟

🧑‍💻秒杀!前端常见手写题!-HowieCong

一、数组扁平化(Flatten)

  • 数组扁平化是将一个嵌套多层的数组转换为只有一层的数组

  • 比如将[1, [2, [3, 4]]]转换为[1, 2, 3, 4]

  • 实现思路:主要围绕遍历数组,判断数组元素是否为数组,如果是则继续深入处理,直到所有元素都为非数组元素,然后将这些元素组合成一个新的一维数组

二、实现方法

(1)使用flat方法(ES6)

这是最简洁的方法,flat方法可以直接将数组扁平化,Infinity参数表示无论数组嵌套多少层都展开

function flattenArray(arr) {
    // 使用flat方法将数组扁平化,Infinity表示无限展开嵌套数组
    return arr.flat(Infinity); 
}
// 测试
let testArr = [1, [2, [3, 4]]];
console.log(flattenArray(testArr));

(2)递归实现

递归遍历数组,遇到数组元素就继续调用自身函数处理,直到所有元素都为非数组元素,再将其添加到结果数组中

function flattenArray(arr) {
    let result = [];
    // 遍历数组
    for (let i = 0; i < arr.length; i++) {
        // 判断当前元素是否为数组
        if (Array.isArray(arr[i])) {
            // 如果是数组,递归调用flattenArray处理,并将结果concat到result数组
            result = result.concat(flattenArray(arr[i])); 
        } else {
            // 如果不是数组,直接将元素push到result数组
            result.push(arr[i]); 
        }
    }
    return result;
}
// 测试
let testArr = [1, [2, [3, 4]]];
console.log(flattenArray(testArr)); 

(3)利用reduce函数迭代

reduce方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。这里利用reduce来迭代处理数组,实现扁平化

function flattenArray(arr) {
    return arr.reduce((prev, next) => {
        // 如果next是数组,递归调用flattenArray处理,然后concat到prev
        // 如果next不是数组,直接concat到prev
        return prev.concat(Array.isArray(next)? flattenArray(next) : next); 
    }, []);
}
// 测试
let testArr = [1, [2, [3, 4]]];
console.log(flattenArray(testArr)); 

(4)扩展运算符实现

通过some方法判断数组中是否还有嵌套数组,如果有则使用扩展运算符将数组展开,直到没有嵌套数组为止

function flattenArray(arr) {
    while (arr.some(item => Array.isArray(item))) {
        // 使用扩展运算符将数组展开并重新赋值给arr
        arr = [].concat(...arr); 
    }
    return arr;
}
// 测试
let testArr = [1, [2, [3, 4]]];
console.log(flattenArray(testArr)); 

(5)splittoString共同处理

先使用toString方法将数组转换为逗号分隔的字符串,再用split方法将字符串分割成数组

function flattenArray(arr) {
    // 将数组转换为字符串,然后分割成数组
    return arr.toString().split(',').map(item => Number(item)); 
}
// 测试
let testArr = [1, [2, [3, 4]]];
console.log(flattenArray(testArr)); 

(6)正则和JSON方法共同处理

先将数组通过JSON.stringify转换为字符串,再用正则表达式去掉字符串中的方括号,最后通过JSON.parse将处理后的字符串转换回数组

function flattenArray(arr) {
    let str = JSON.stringify(arr);
    // 去掉字符串中的方括号
    str = str.replace(/[|]/g, ''); 
    // 为字符串两端加上方括号,使其符合数组格式
    str = '[' + str + ']'; 
    return JSON.parse(str);
}
// 测试
let testArr = [1, [2, [3, 4]]];
console.log(flattenArray(testArr)); 

三、讨论

(1)flat参数和Infinity的区别

  • flat方法的参数depth表示展开的深度,默认值为 1,即展开一层数组。如果不传参数,就按照默认值 1 展开;传Infinity则表示无论数组嵌套多少层都展开,实现彻底的扁平化

(2)递归实现扁平化的优缺点

  • 优点:逻辑清晰,易于理解,符合人类的思维方式,对于处理复杂的嵌套结构非常直观

  • 缺点:性能方面,递归调用会占用大量的栈空间,如果数组嵌套层数过深,可能会导致栈溢出错误。而且递归函数的执行效率相对较低,因为每次递归调用都需要创建新的函数调用栈

(3)选择哪种方法进行扁平化

  • 如果项目支持 ES6 语法,优先选择flat方法,因为它代码简洁,易于维护,而且性能较好,是 JavaScript 原生提供的方法,经过了优化

  • 如果项目环境不支持 ES6,根据具体情况选择,比如数据量不大且嵌套层数不深,可以使用递归或reduce方法

  • 如果追求性能且对代码可读性要求不是特别高,可以考虑扩展运算符实现

(4)数组中的nullundefined等特殊值的处理方法

  • flat方法、递归实现、reduce函数迭代、扩展运算符实现 这几种方法都会将nullundefined等特殊值当作普通元素正常处理,保留在扁平化后的数组中

  • splittoString共同处理的方法会将nullundefined转换为字符串"null""undefined" ,然后保留在扁平化后的数组中

  • 正则和JSON方法共同处理同样会将nullundefined转换为字符串形式保留在数组中

(5)指定层级扁平化

  • 可添加depth参数控制递归深度。例如修改递归法

    function flatten(arr, depth = Infinity) {
      return arr.reduce((acc, cur) => {
        if (Array.isArray(cur) && depth > 0) {
          acc.push(...flatten(cur, depth - 1)); // 每递归一次深度减1
        } else {
          acc.push(cur);
        }
        return acc;
      }, []);
    }
    

❓其他

1. 疑问与作者HowieCong声明

  • 如有疑问、出错的知识,请及时点击下方链接添加作者HowieCong的其中一种联系方式或发送邮件到下方邮箱告知作者HowieCong

  • 若想让作者更新哪些方面的技术文章或补充更多知识在这篇文章,请及时点击下方链接添加里面其中一种联系方式或发送邮件到下方邮箱告知作者HowieCong

  • 声明:作者HowieCong目前只是一个前端开发小菜鸟,写文章的初衷只是全面提高自身能力和见识;如果对此篇文章喜欢或能帮助到你,麻烦给作者HowieCong点个关注/给这篇文章点个赞/收藏这篇文章/在评论区留下你的想法吧,欢迎大家来交流!

2. 作者社交媒体/邮箱-HowieCong