如果在递归函数中调用了“ 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循环之前添加了一个切换开关,这样,如果我们碰巧从每个数组中获得一个匹配项,那么从逻辑上讲,我们需要检查所有其他可能性,因为它们可能是有效的。否则,如果我们没有获得真正的结果就克服了一切,那就打破一切,因为不再有任何可能性。
答案 0 :(得分:1)
都不是。像break
和continue
这样的循环控制语句仅在循环(for
,while
,do
或switch
)内有效。您的代码中的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在下面的评论中解释的那样)。
从技术上讲,这不是“爆发”,而是在返回之前回滚呼叫链,这是(恕我直言)最干净的方法(尽管从技术上讲,它不如一次闯入那样理想)。坚持使用递归函数。