在JavaScript中打破嵌套循环的最佳方法是什么?

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不同,这些标签只能用于continuebreak,因为Javascript没有goto


将其包裹在函数中然后只需return


我有点迟到了,但以下是与语言无关的方法,不使用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;}
}


如何完全不使用中断,没有中止标志,也没有额外的条件检查。这个版本只是在满足条件时抛出循环变量(使它们成为Number.MAX_VALUE)并强制所有循环优雅地终止。

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()函数。这种方法的另一个好处是Object.keys()只枚举了一个对象自己的可枚举属性,而"for-in循环也枚举了原型链中的属性"。

接近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)当开始下一次迭代时,使用保持索引值启动内部循环。