• 数组扁平化


    start

    • 经常看到有数组扁平化的题目。
    • 看别人写的上来就好几种数组扁平化的方式,自己亲手写一写,变成自己的知识。

    1. flat

    ES6 在数组上新增的方法:Array.prototype.flat ;

    const arr1 = [0, 1, 2, [3, 4]]
    console.log(arr1.flat())
    // expected output: [0, 1, 2, 3, 4]
    
    const arr2 = [0, 1, 2, [[[3, 4]]]]
    console.log(arr2.flat(2))
    // expected output: [0, 1, 2, [3, 4]]
    
    const arr3 = [0, 1, 2, [[[3, 4]]]]
    console.log(arr3.flat(Infinity))
    // expected output: [ 0, 1, 2, 3, 4 ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    个人总结

    • flat:英文释义:平的,平坦的;
    • arr.flat([depth]), depth 指定要提取嵌套数组的结构深度,默认值为 1;
    • 返回一个包含将数组与子数组中所有元素的新数组;(扁平化不会修改原数组
    • 使用 Infinity,可展开任意深度的嵌套数组;
    • flat() 方法会移除数组中的空项:

    2. toString + split + map

    var arr = [1, 2, 3, [4, 5, [6, 7, 8]]]
    
    var newArr = arr
      .toString()
      .split(',')
      .map((item) => parseFloat(item))
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    个人总结

    • 只针对纯数字的多维数组;
    • 数组项存在字符串,例如:[1,2,'3'],使用这种方法,就会修改原数组;
    • map 的作用就是用来还原数组每一项的类型;
    • 字符串转数组,方法很多: parseFloat+

    3. reduce + concat + isArray + recursivity(递归)

    // 使用 reduce、concat 和递归展开无限多层嵌套的数组
    var arr1 = [1, 2, 3, [1, 2, 3, 4, [2, 3, 4]]]
    function flatDeep(arr, d = 1) {
      return d > 0
        ? arr.reduce(
            (acc, val) =>
              acc.concat(Array.isArray(val) ? flatDeep(val, d - 1) : val),
            []
          )
        : arr.slice()
    }
    
    flatDeep(arr1, Infinity)
    // [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    个人总结

    • 主要思想就是递归;
    • 其次就是 reduce 的基本用法;
    • 再复习一下 reduce 的基础用法:
      • 两个参数,一个参数为回调函数,一个参数为初始值;
      • 回调函数的参数依次为:上一次调用的返回值;当前项;当前项索引;正在处理的数组;

    4.forEach + isArray + push + recursivity(递归)

    // forEach 遍历数组会自动跳过空元素
    const eachFlat = (arr = [], depth = 1) => {
      const result = [] // 缓存递归结果
      // 开始递归
      ;(function flat(arr, depth) {
        // forEach 会自动去除数组空位
        arr.forEach((item) => {
          // 控制递归深度
          if (Array.isArray(item) && depth > 0) {
            // 递归数组
            flat(item, depth - 1)
          } else {
            // 缓存元素
            result.push(item)
          }
        })
      })(arr, depth)
      // 返回递归结果
      return result
    }
    
    // for of 循环不能去除数组空位,需要手动去除
    const forFlat = (arr = [], depth = 1) => {
      const result = []
      ;(function flat(arr, depth) {
        for (let item of arr) {
          if (Array.isArray(item) && depth > 0) {
            flat(item, depth - 1)
          } else {
            // 去除空元素,添加非 undefined 元素
            item !== void 0 && result.push(item)
          }
        }
      })(arr, depth)
      return result
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    个人总结

    • 循环加递归;
    • 需要注意的是 for 循环不会跳过空元素,forEach 会,例如:([1,,3].forEach(i=>{console.log('tomato',i)}))。

    5. 使用堆栈 stack

    // 无递归数组扁平化,使用堆栈
    // 注意:深度的控制比较低效,因为需要检查每一个值的深度
    // 也可能在 shift / unshift 上进行 w/o 反转,但是末端的数组 OPs 更快
    var arr1 = [1, 2, 3, [1, 2, 3, 4, [2, 3, 4]]]
    function flatten(input) {
      const stack = [...input]
      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()
    }
    flatten(arr1) // [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    个人总结

    • 基本原理就就是遇到数组就解构。

    6. Use Generator function

    function* flatten(array) {
      for (const item of array) {
        if (Array.isArray(item)) {
          yield* flatten(item)
        } else {
          yield item
        }
      }
    }
    
    var arr = [1, 2, [3, 4, [5, 6]]]
    const flattened = [...flatten(arr)]
    // [1, 2, 3, 4, 5, 6]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    个人总结

    • Generator 的说明
    • flatten(arr)返回的是遍历器对象,然后通过解构运算符,依次执行。
    • 本质还是递归的思想。

    end

    • 数组扁平化总结:
      • 不修改原数组;
      • 如果需要手写实现,优先考虑递归;
  • 相关阅读:
    Linux CentOS7 添加网卡
    F. Conditional Mix(数论/dp)
    酷早报:9月5日Web3加密行业新闻大汇总
    鸿鹄工程项目管理系统 Spring Cloud+Spring Boot+前后端分离构建工程项目管理系统
    计算机毕业设计Python+Django的银行取号排队系统(源码+系统+mysql数据库+Lw文档)
    VB:顺序查找
    MSOS604A是德科技keysight MSOS604A示波器
    计算机网络:关键性能指标与非性能特征解析
    前端性能优化——启用文本压缩
    源码中的设计模式--模板方法模式(钩子方法)
  • 原文地址:https://blog.csdn.net/wswq2505655377/article/details/126356488