What's the best way to break from nested loops in JavaScript?
在Javascript中打破嵌套循环的最佳方法是什么?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //Write the links to the page. for (var x = 0; x < Args.length; x++) { for (var Heading in Navigation.Headings) { for (var Item in Navigation.Headings[Heading]) { if (Args[x] == Navigation.Headings[Heading][Item].Name) { document.write("<a href="" + Navigation.Headings[Heading][Item].URL +"">" + Navigation.Headings[Heading][Item].Name +" :"); break; // <---HERE, I need to break out of two loops. } } } } |
就像Perl一样
1 2 3 4 5 6 7 8 9 10 | loop1: for (var i in set1) { loop2: for (var j in set2) { loop3: for (var k in set3) { break loop2; // breaks out of loop3 and loop2 } } } |
如EMCA-262第12.12节中的定义。 [MDN Docs]
与C不同,这些标签只能用于
将其包裹在函数中然后只需
我有点迟到了,但以下是与语言无关的方法,不使用GOTO /标签或功能包装:
1 2 3 4 5 6 7 8 9 10 11 | for (var x = Set1.length; x > 0; x--) { for (var y = Set2.length; y > 0; y--) { for (var z = Set3.length; z > 0; z--) { z = y = -1; // terminates second loop // z = y = x = -1; // terminate first loop } } } |
在好的方面,它自然流动,这应该取悦非GOTO人群。在缺点方面,内部循环需要在终止之前完成当前迭代,因此在某些情况下可能不适用。
我意识到这是一个非常古老的话题,但由于我的标准方法还没有到来,我想我会把它发布给未来的googlers。
1 2 3 4 5 6 7 8 9 | var a, b, abort = false; for (a = 0; a < 10 && !abort; a++) { for (b = 0; b < 10 && !abort; b++) { if (condition) { doSomeThing(); abort = true; } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var str =""; for (var x = 0; x < 3; x++) { (function() { // here's an anonymous function for (var y = 0; y < 3; y++) { for (var z = 0; z < 3; z++) { // you have access to 'x' because of closures str +="x=" + x +" y=" + y +" z=" + z +"<br />"; if (x == z && z == 2) { return; } } } })(); // here, you execute your anonymous function } |
怎么样? :)
非常简单
1 2 3 4 5 6 7 8 9 10 11 | var a=[1,2,3]; var b=[4,5,6]; var breakCheck1=false; for (var i in a){ for (var j in b){ breakCheck1=true; break; } if (breakCheck1) {break;} } |
如何完全不使用中断,没有中止标志,也没有额外的条件检查。这个版本只是在满足条件时抛出循环变量(使它们成为
1 2 3 4 5 6 7 8 9 | // No breaks needed for (var i = 0; i < 10; i++) { for (var j = 0; j < 10; j++) { if (condition) { console.log("condition met"); i = j = Number.MAX_VALUE; // Blast the loop variables } } } |
对于递减类型的嵌套循环,有一个类似的答案,但是这适用于递增类型的嵌套循环,而不需要考虑简单循环的每个循环的终止值。
另一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 | // No breaks needed for (var i = 0; i < 89; i++) { for (var j = 0; j < 1002; j++) { for (var k = 0; k < 16; k++) { for (var l = 0; l < 2382; l++) { if (condition) { console.log("condition met"); i = j = k = l = Number.MAX_VALUE; // Blast the loop variables } } } } } |
以下是在JavaScript中打破嵌套循环的五种方法:
1)将父循环设置为结尾
1 2 3 4 5 6 7 8 9 10 11 | for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { if (j === 2) { i = 5; break; } } } |
2)使用标签
1 2 3 4 5 6 7 8 9 | exit_loops: for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { if (j === 2) break exit_loops; } } |
3)使用变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var exit_loops = false; for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { if (j === 2) { exit_loops = true; break; } } if (exit_loops) break; } |
4)使用自执行功能
1 2 3 4 5 6 7 8 9 10 11 | (function() { for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { if (j === 2) return; } } })(); |
5)使用常规功能
1 2 3 4 5 6 7 8 9 10 11 12 | function nested_loops() { for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { if (j === 2) return; } } } nested_loops(); |
如何将循环推到最终限制
1 2 3 4 5 6 7 8 9 10 11 12 | for(var a=0; a<data_a.length; a++){ for(var b=0; b<data_b.length; b++){ for(var c=0; c<data_c.length; c++){ for(var d=0; d<data_d.length; d++){ a = data_a.length; b = data_b.length; c = data_b.length; d = data_d.length; } } } } |
如果你使用Coffeescript,有一个方便的"do"关键字,可以更容易地定义和立即执行匿名函数:
1 2 3 4 5 | do -> for a in first_loop for b in second_loop if condition(...) return |
...所以你可以简单地使用"return"来摆脱循环。
我以为我会展示一种功能编程方法。您可以在我的解决方案中打破嵌套的Array.prototype.some()和/或Array.prototype.every()函数。这种方法的另一个好处是
接近OP的解决方案:
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 | Args.forEach(function (arg) { // This guard is not necessary, // since writing an empty string to document would not change it. if (!getAnchorTag(arg)) return; document.write(getAnchorTag(arg)); }); function getAnchorTag (name) { var res = ''; Object.keys(Navigation.Headings).some(function (Heading) { return Object.keys(Navigation.Headings[Heading]).some(function (Item) { if (name == Navigation.Headings[Heading][Item].Name) { res = ("<a href="" + Navigation.Headings[Heading][Item].URL +"">" + Navigation.Headings[Heading][Item].Name +" :"); return true; } }); }); return res; } |
减少迭代标题/项目的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | var remainingArgs = Args.slice(0); Object.keys(Navigation.Headings).some(function (Heading) { return Object.keys(Navigation.Headings[Heading]).some(function (Item) { var i = remainingArgs.indexOf(Navigation.Headings[Heading][Item].Name); if (i === -1) return; document.write("<a href="" + Navigation.Headings[Heading][Item].URL +"">" + Navigation.Headings[Heading][Item].Name +" :"); remainingArgs.splice(i, 1); if (remainingArgs.length === 0) return true; } }); }); |
之前已经提到过swilliams,但下面有一个例子(Javascript):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | // Function wrapping inner for loop function CriteriaMatch(record, criteria) { for (var k in criteria) { if (!(k in record)) return false; if (record[k] != criteria[k]) return false; } return true; } // Outer for loop implementing continue if inner for loop returns false var result = []; for (var i = 0; i < _table.length; i++) { var r = _table[i]; if (!CriteriaMatch(r[i], criteria)) continue; result.add(r); } |
嗯嗨到10岁的派对?
为什么不给你一些条件?
1 2 3 4 5 6 7 8 | var condition = true for (var i = 0 ; i < Args.length && condition ; i++) { for (var j = 0 ; j < Args[i].length && condition ; j++) { if (Args[i].obj[j] =="[condition]") { condition = false } } } |
这样你就可以随心所欲地停下来
在我的例子中,使用Typescript,我们可以使用some()来遍历数组并在满足条件时停止
所以我的代码变成这样:
1 2 3 4 5 | Args.some((listObj) => { return listObj.some((obj) => { return !(obj =="[condition]") }) }) |
像这样,循环在条件满足后立即停止
提醒:此代码在TypeScript中运行
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 | XXX.Validation = function() { var ok = false; loop: do { for (...) { while (...) { if (...) { break loop; // Exist the outermost do-while loop } if (...) { continue; // skips current iteration in the while loop } } } if (...) { break loop; } if (...) { break loop; } if (...) { break loop; } if (...) { break loop; } ok = true; break; } while(true); CleanupAndCallbackBeforeReturning(ok); return ok; }; |
最好的方法是 -
1)对在第一个和第二个循环中使用的两个数组进行排序。
2)如果项目匹配则打破内部循环并保持索引值。
3)当开始下一次迭代时,使用保持索引值启动内部循环。