【问题标题】:Check if an element is an array using recursion使用递归检查元素是否为数组
【发布时间】:2021-11-19 22:54:14
【问题描述】:

我想检查一个数组中的元素是否是另一个数组。我正在解决一个代码挑战,其中问题是遍历数组并检查 7 但如果 element 是一个数组,我想连续检查每个嵌套数组是否有 7。

我的第一个'if'语句中有console.log(),并且我看到sevenBoom() 被多次调用。但由于某种原因,它没有返回“Boom!”

SevenBoom 应该返回“Boom!”如果有七。

    function sevenBoom(arr) {
      if (arr.includes(7)) {
        return "Boom!";
      }
    
      arr.forEach((val) => {
        if (Array.isArray(val)) sevenBoom(val);
      });
    }

    sevenBoom([1, 3, 4, 6, [7]) // Returns undefined
    sevenBoom([3, 7, 8, 9]) // Returns 'Boom!'

【问题讨论】:

  • 您能否将一些示例输入作为minimal reproducible example 添加到您的问题中。
  • sevenBoom 正在返回一些东西;那么为什么忽略forEach 中的返回值呢?你为什么使用forEach 无论如何都会忽略返回值?请改用some
  • 或者只是做 flat(),但你的问题是你永远不会从 forEach 返回,而在这种情况下使用 forEach 确实是错误的。
  • 对于没有7 值的数组,您期望什么返回值?
  • @NinaScholz 哦,我只是要添加一个 else 语句,返回一个带有“没有 7”的字符串。就是这样。

标签: javascript arrays recursion


【解决方案1】:

您可以将布尔值作为结果并使用Array#some 来检查数组。

function hasSeven(array) {
    function seven(a) {
        return a.includes(7) || a.some(v => Array.isArray(v) && seven(v));
    }
    return seven(array)
        ? 'Boom!'
        : 'There is no 7';
}


console.log(hasSeven([7]));
console.log(hasSeven([[7]]));
console.log(hasSeven([[[7]]]));

console.log(hasSeven([]));
console.log(hasSeven([[]]));
console.log(hasSeven([[[]]]));

【讨论】:

    【解决方案2】:
    const sevenBoom = (arr) => {
      const recurse = (arr) => arr.some(n => Array.isArray(n) ? recurse(n) : n === 7);
    
      if (recurse(arr)) {
        return 'Boom';
      }
    }
    

    这是假设除了“Boom”之外应该返回的是void。这对于递归来说有点尴尬,因为如果你满足某些条件,你想返回一个字符串,否则什么都没有。

    【讨论】:

      【解决方案3】:

      首先,您还需要从第二个 if 条件中返回值。

      forEach() 不能被打断(例如:使用 return 语句)并且会为所有项目运行。因此,您可以使用forEach() 之外的标志变量进行跟踪,并在此基础上返回您的结果。

        function sevenBoom(arr) {
            if (arr.includes(7)) {
              return "Boom!";
            }
             let found = false;
            arr.forEach((val) => {
              if (Array.isArray(val))                          if(sevenBoom(val)) found="Boom!"; 
            })
          return found;
      }
          
          console.log(sevenBoom([1,2,3]));
          console.log(sevenBoom([1,2,7]));
          console.log(sevenBoom([1,2,[2,7]]));
          console.log(sevenBoom([1,2,[2,3,[4,5]]]));
          console.log(sevenBoom([1,2,[2,3,[4,7]]]));
          

      注意:sevenBoom() 如何在 if 语句中直接使用。这是因为truthyfalsy 值的概念。

      PS:如上所述,forEach() 将运行所有项目,无论如何。您可以使用任何其他循环机制,例如简单的for loopsome() 等。我只是复制了您的代码,因此使用了forEach()

      【讨论】:

      • 发现后为什么还要继续检查?
      • 只是想更新 OP 编写的代码。没有改变循环机制。
      【解决方案4】:

      我会在你检查一个元素是否是一个数组的同一个循环中检查一个元素是否为 7,这样你就可以避免不必要地遍历数组。

      const sevenBoom = arr => {
          for (const ele of arr) {
              if (ele === 7) return 'Boom';
      
              if (Array.isArray(ele)) {
                  //this prevents you from halting your function early
                  //you only want to return in the loop if a 7 is found
                  if (boom(ele) === 'Boom') return 'boom'
              }
          }
      }
      

      【讨论】:

        【解决方案5】:

        在使用.includes() 方法之前,您可以使用.flat(depth) 方法来展平每个数组。为您的项目选择一个涵盖所有可能数组的深度。

        function sevenBoom(arr) {
            return arr.flat(10).includes(7) ? 'Boom!' : '-'
        }
        

        演示

        let a = [1, 3, 4, 6, [7]],
            b = [3, 7, 8, 9],
            c = [1,2,[5,6,[3,5,[7,6]]]],
            d = [0],
            e = [1, [5, 4], 3, 5, [7]];
        
        function sevenBoom(arr) {
            return arr.flat(10).includes(7) ? 'Boom!' : '-'
        }
        
        for(let arr of [a,b,c,d,e]) {
            console.log( sevenBoom( arr ) );
        }
        
        console.log( e ); //Original array remains unchanged

        【讨论】:

          【解决方案6】:

          如果根数组中不存在 7,则您的函数不会返回任何内容。 试试这个,只是一个小的重构:

          function sevenBoom(arr) {
              if (arr.includes(7)) return 'Boom!';
          
              for (let val of arr) {
                if (Array.isArray(val)) {
                  if (sevenBoom(val)) return sevenBoom(val);
                }
              }
          
            return false;
          }
          

          【讨论】:

          • 谢谢!!我正在研究其他问题,我盯着它们看的时间有点太长了,我意识到看着 SO 递归答案我快要脑死了。我知道我忽略了一些东西。我的 forEach 是一个可怕的选择,smh。再次感谢。
          • 注意:这不适用于[1, [5, 4], 3, 5, [7]]
          • 是的,它不会,我已经相应地编辑了答案
          猜你喜欢
          • 1970-01-01
          • 2020-11-14
          • 2021-04-15
          • 1970-01-01
          • 2016-05-07
          • 1970-01-01
          • 2019-03-11
          • 2019-03-15
          • 2014-03-26
          相关资源
          最近更新 更多