美文网首页
JS:展开多维数组的 10 种方法(可控制深度)

JS:展开多维数组的 10 种方法(可控制深度)

作者: limengzhe | 来源:发表于2021-09-27 10:36 被阅读0次

    JS:展开多维数组的 10 种方法(可控制深度)

    [1, [2, 3, [4, 5, [6, 7, 8, [9, 10]]]]]
    
    👇
    
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    
    1. 使用 Array.prototype.flat() 方法(可控制深度)

      ES2019 新增了 Array.prototype.flat() 方法,该方法可以按照指定的深度将多维数组展开,然后作为一个新数组返回。深度的默认值为 1。如果想要全部展开,只需传递一个 Infinity(无穷大) 即可。

      console.log(sourceData.flat()) // [1, 2, 3, [4, 5, [6, 7, 8, [9, 10]]]]
      console.log(sourceData.flat(Infinity)) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      

      但是 IE 浏览器并不支持此方法,所以需要进行 polyfill。但是不要担心,下面有九种 polyfill 方法供我们选择。

    2. 使用 for() 循环进行递归

      使用 for() 循环依次判断每一项是否是数组,如果是,调用此方法继续遍历,如果不是,直接添加到返回值数组中,直到全部展开。

      function flatByFor(arr) {
        const res = []
      
        for (let i = 0; i < arr.length; i++) {
          Array.isArray(arr[i]) ? res.push(...flatByFor(arr[i])) : res.push(arr[i])
        }
      
        return res
      }
      
      console.log(flatByFor(sourceData)) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      
    3. for() 递归增强版(可控制深度)

      可以将深度作为参数传递,在展开时判断是否达到指定的深度,如果达到指定的深度,则直接添加到返回值数组中,否则继续遍历。

      function deepFlatByFor(arr, depth = Infinity) {
        const res = []
      
        for (let i = 0; i < arr.length; i++) {
          Array.isArray(arr[i]) && depth > 0
            ? res.push(...deepFlatByFor(arr[i], depth - 1))
            : res.push(arr[i])
        }
      
        return res
      }
      
      console.log(deepFlatByFor(sourceData)) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      console.log(deepFlatByFor(sourceData, 2)) // [1, 2, 3, 4, 5, [6, 7, 8, [9, 10]]]
      
    4. 使用 forEach() 进行递归

      for() 类似,只是使用 Array.prototype.forEach() 方法。

      function flatByForEach(arr) {
        const res = []
      
        arr.forEach(item => {
          Array.isArray(item) ? res.push(...flatByForEach(item)) : res.push(item)
        })
      
        return res
      }
      
      console.log(flatByForEach(sourceData)) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      
    5. forEach() 递归增强版(可控制深度)

      for() 类似,只是使用 Array.prototype.forEach() 方法。

      function deepFlatByForEach(arr, depth = Infinity) {
        const res = []
      
        arr.forEach(item => {
          Array.isArray(item) && depth > 0
            ? res.push(...deepFlatByForEach(item, depth - 1))
            : res.push(item)
        })
      
        return res
      }
      
      console.log(deepFlatByForEach(sourceData)) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      console.log(deepFlatByForEach(sourceData, 2)) // [1, 2, 3, 4, 5, [6, 7, 8, [9, 10]]]
      
    6. 使用 while() 循环配合 Array.prototype.some() 判断

      使用 Array.prototype.some() 方法检测数组中是否还存在数组,将其作为 while() 的执行条件,如果有数组可一直执行,而 Array.prototype.concat() 方法可以将多个数组合并到一个数组中,所以这里我们只需要利用扩展运算符不断的将数组展开合并即可。

      function flatByWhileSome(arr) {
        while (arr.some(item => Array.isArray(item))) {
          arr = [].concat(...arr)
        }
      
        return arr
      }
      
      console.log(flatByWhileSome(sourceData)) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      
    7. while() 循环配合 Array.prototype.some() 增强版(可控制深度)

      function deepFlatByWhileSome(arr, depth = Infinity) {
        while (arr.some(item => Array.isArray(item)) && depth > 0) {
          arr = [].concat(...arr)
          depth--
        }
      
        return arr
      }
      
      console.log(deepFlatByWhileSome(sourceData)) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      console.log(deepFlatByWhileSome(sourceData, 2)) // [1, 2, 3, 4, 5, [6, 7, 8, [9, 10]]]
      
    8. 使用 while() 循环配合 Array.prototype.shift() 判断

      使用 shift() 方法将数组中的元素依次取出并判断是否为数组,如果是,将其展开后并再次存入,等待下一次遍历,如果不是,则将其存入返回值数组,直到全部展开。由于 shift() 方法会改变原数组,所以我们需要将原数组复制一份,然后再进行遍历。

      function flatByWhileShift(arr) {
        const res = []
        const stack = [...arr] // 或 arr.slice()
      
        while (stack.length) {
          const next = stack.shift()
          Array.isArray(next) ? stack.push(...next) : res.push(next)
        }
      
        return res
      }
      
      console.log(flatByWhileShift(sourceData)) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      
    9. 使用 reduce() 配合 Array.prototype.concat() 进行递归

      reduce() 方法可以从左到右依次对数组中的元素执行传入的函数,并返回执行结果。所以我们在传给 reduce() 的函数中,将不是数组的元素直接使用 concat() 方法拼接到返回值数组,将是数组的元素递归调用此方法再进行拼接。

      function flatByReduce(arr) {
        return arr.reduce((acc, cur) => {
          return acc.concat(Array.isArray(cur) ? flatByReduce(cur) : cur)
        }, [])
      }
      
      console.log(flatByReduce(sourceData)) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      
    10. reduce() 递归增强版(可控制深度)

      function deepFlatByReduce(arr, depth = Infinity) {
        return depth > 0
          ? arr.reduce(
              (acc, cur) =>
                acc.concat(
                  Array.isArray(cur) ? deepFlatByReduce(cur, depth - 1) : cur
                ),
              []
            )
          : arr.slice()
      }
      
      console.log(deepFlatByReduce(sourceData)) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      console.log(deepFlatByReduce(sourceData, 2)) // [1, 2, 3, 4, 5, [6, 7, 8, [9, 10]]]
      

    参考资料:

    相关文章

      网友评论

          本文标题:JS:展开多维数组的 10 种方法(可控制深度)

          本文链接:https://www.haomeiwen.com/subject/ilyhnltx.html