javascript“中断”将完全停止递归函数还是仅停止该实例?

时间:2018-11-20 03:46:43

标签: javascript arrays

如果在递归函数中调用了“ break”,它将中断它被调用的所有迭代,还是会取消该实例?具体来说,我想了解以下代码:

//take a 2d array and check if it is in _switch
function checkSwitch(arr2d, rates, n = 0, found = []){
    if(n===arr2d.length){
        inCase(found, rates)
        break
    }
    for(let i in arr2d[n]){
        if(deepCheck(_switch, [...found, arr2d[n][i]]))
        checkSwitch(arr2d, rates, n+1, [...found, arr2d[n][i]])
    }
    return false
}

我有一个二维数组(数组数组),我检查每个数组中是否有一个元素作为嵌套对象键包含在此_switch中。当我有一个完全匹配项时,然后运行一个函数,我想继续检查2d数组以查看是否还有其他匹配项。

但是,如果我遇到一个没有匹配项的数组,那么我需要中断递归的所有迭代以提高效率,因为我知道逻辑上每个匹配项都不存在任何匹配项。

所以我需要能够破坏一个实例并破坏所有实例。我不确定如何获得。

正确的代码和经验教训 我对在从事人工智能工作时实际上了解到的智能感到惊讶。在递归函数中,添加返回值将破坏当前实例,如果在调用递归时检查了返回值,则可以传回整个递归的折叠。这是新代码:

function checkSwitch(arr2d, rates, n = 0, found = []) {
    if (n === arr2d.length) {
        inCase(found, rates);
        return true;
    }
    let tf = false
    for (let i in arr2d[n]) {
        if (deepCheck(_switch, [...found, arr2d[n][i]])) {
            if (!checkSwitch(arr2d, rates, n + 1, [...found, arr2d[n][i]])) {
                return false;
            } else {
                tf = true
            }
        }
    }
    return tf;
}

返回true表示中断此迭代并继续进行,而返回false表示中断所有操作。我在for循环之前添加了一个切换开关,这样,如果我们碰巧从每个数组中获得一个匹配项,那么从逻辑上讲,我们需要检查所有其他可能性,因为它们可能是有效的。否则,如果我们没有获得真正的结果就克服了一切,那就打破一切,因为不再有任何可能性。

3 个答案:

答案 0 :(得分:1)

都不是。像breakcontinue这样的循环控制语句仅在循环(forwhiledoswitch)内有效。您的代码中的break语句不在循环中,因此此代码将导致语法错误。

“突破”多个级别的递归函数的唯一方法是引发异常。对于这种情况,这可能不理想;针对您的情况的一个更好的选择可能是使用嵌套循环而不是递归。

答案 1 :(得分:0)

break statement将仅终止当前循环,开关或标签语句。这是错误的工具,无法用于您要完成的任务。 (因为它不在这些构造之一中,所以不要在任何地方使用它。)更好的方法是让checkSwitch返回一个值,该值指示是否应放弃匹配过程。然后,该值可以渗透回递归堆栈。或者,抛出一个异常(然后您必须在该异常中捕获)。

答案 2 :(得分:0)

您可以简单地使用return代替,并始终从呼叫者的角度检查结果。在这种情况下,您需要在“中断”时返回另一个值:

function checkSwitch(arr2d, rates, n = 0, found = []) {
  if (n === arr2d.length) {
    inCase(found, rates);
    return true;
  }
  for (let i in arr2d[n]) {
    if (deepCheck(_switch, [...found, arr2d[n][i]])) {
      if (checkSwitch(arr2d, rates, n + 1, [...found, arr2d[n][i]])) {
        return true;
      }
    }
  }
  return false;
}

在这里,返回true基本上意味着“停止一切”(爆发),返回false意味着正常停止当前迭代(如OP在下面的评论中解释的那样)。

从技术上讲,这不是“爆发”,而是在返回之前回滚呼叫链,这是(恕我直言)最干净的方法(尽管从技术上讲,它不如一次闯入那样理想)。坚持使用递归函数。