How to break nested loops in JavaScript? [duplicate]
Asked Answered
C

14

250

I tried this:

for(i = 0; i < 5; i++){
    for(j = i + 1; j < 5; j++){
        break(2);
    }
    alert(1);
}

only to get:

SyntaxError: missing ; before statement

So, how would I break a nested loop in JavaScript?

Crymotherapy answered 14/10, 2009 at 7:42 Comment(7)
break ( 2) ; :o what do you mean by 2, break can't have any argumentsCostanza
Line 7 is missing a semicolon after alert(1).Methaemoglobin
@Nathan Taylor: semicolons are optional in JavaScript, but considered good styleExon
Near duplicate of https://mcmap.net/q/63888/-what-39-s-the-best-way-to-break-from-nested-loops-in-javascript-closed/149391Baronage
@RakeshJuyal it does in other languages such as CContemporize
@NathanTaylor I don't consider semicolons good style at all XDPorism
@RakeshJuyal I guess you can choose how many scopes you want to break.Porism
E
660

You should be able to break to a label, like so:

function foo () {
    dance:
    for (var k = 0; k < 4; k++) {
        for (var m = 0; m < 4; m++) {
            if (m == 2) {
                break dance;
            }
        }
    }
}
Essam answered 14/10, 2009 at 7:47 Comment(5)
break dance har harSynthetic
There's also the fact that JS requires this giant involved dance. Other languages give you a break (literally, like break 2).Circumstance
Would it be the same if dance: was after the for? Or does the label need to be read before the break?Porism
By the way, why does breaking the parent loop also break the child loop instantly?Enmity
If the parent loop isn't being executed, how could the child loop be?Brainwork
I
54

You need to name your outer loop and break that loop, rather than your inner loop - like this.

outer_loop: 
for(i=0;i<5;i++) {
    for(j=i+1;j<5;j++) {
        break outer_loop;
    }
    alert(1);
}
Incogitant answered 14/10, 2009 at 7:49 Comment(7)
Wow, I didn't know we can name loops, great info! +1Meliorate
@o.k.w: you don't name the loop. You just label a position in the source.Flicker
Never knew JavaScript supported labels. I wonder why I've never seen that before. :OMethaemoglobin
@xtofl: Not exactly. You associate a label with a statement (which could be a loop) by placing it immediately before. It's only useful with a block statement, since the label is only available with the break and continue statements within the block.Cullum
@Nathan: probably because it's very poor practice: if you need to use labels in your code, it's a sign that you need to rewrite your code ;-)Shakhty
@NickFitz: you could make a performance argument for it. In the case of nested loops labels could be useful to break out of an outer loop. While it may more elegant and modular to avoid nested loops by moving inner loops to separate functions, it will run marginally slower because of the extra function calls.Cullum
labels are the reason something like onclick:"javascript: doThis()" doesn't cause an error. javascript: is considered an unnecessary label in that case.Pouliot
L
40

There are at least five different ways to break out of two or more loops:

1) Set parent(s) loop to the end

for (i = 0; i < 5; i++)
{
    for (j = 0; j < 5; j++)
    {
        if (j === 2)
        {
            i = 5;
            break;
        }
    }
}

2) Use label

fast:
for (i = 0; i < 5; i++)
{
    for (j = 0; j < 5; j++)
    {
        if (j === 2)
            break fast;
    }
}

3) Use variable

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) Use self executing function

(function()
{
    for (i = 0; i < 5; i++)
    {
        for (j = 0; j < 5; j++)
        {
             if (j === 2)
                 return;
        }
    }
})();

5) Use regular function

function nested_loops()
{
    for (i = 0; i < 5; i++)
    {
        for (j = 0; j < 5; j++)
        {
             if (j === 2)
                 return;
        }
    }
}
nested_loops();
Leptospirosis answered 5/8, 2018 at 12:26 Comment(3)
The whole point of a multi-level break is to avoid #3.Diatomite
break fast 😄Neglect
Never knew of using labels, I'm gonna use that heaps nowAccusal
I
30

See Aaron's. Otherwise: j=5;i=5 instead of break.

Intermarry answered 14/10, 2009 at 7:49 Comment(9)
This is simply the best and cleanest solution. Don't go back to using labels, they look awful.Tremml
This is ugly. for(i=0;i<5;i++) is supposed to run 5 times. Updating i outside of the loop statement makes it behave in an unexpected way.Quart
Ugly is subjective. The loop is supposed to run as many times as you want it to run. The question was how to break a double for-loop, in that neither j or i run to 5. The only technical reason for favouring mine vs "break dance" is the case where you want i/j to show completion (==5) vs incompletion (== <5) post loops.Intermarry
Agree with @FlorianF, this is ugly in the sense that it seems to be a more error prone solution than adding a label, although I don't have any statistical evidence for that. Whether you are used to labels or not, they are certainly not an error-free concept, but hard coding numbers that you have to change at multiple places if one changes is a horrible programming style. As to the evaluation, it is a fair statement and helpful to determine the best answer for the OP.Firehouse
@Manuel: re:"horrible programming style". You're free to use consts etc for the numbers in both places, but that's not relevant to the question. Since this was answered in 2009, today I'd say you should rewrite your code so you don't need to use a for-loop. (filter, reduce, map, etc..)Intermarry
@Intermarry the question is "how to break a for-loop", so the answer is still relevant today, regardless of the availability of higher order functions. If adding an additional var declaration is necessary to make this an answer that is actually practicable, then it should be added to the answer to reveal the full complexity. Practicability, maintainability, complexity are key factors when evaluating an answer.Firehouse
@Firehouse there's a difference between production code and understanding how something works. The question is "how to break from nested loops", not "how do I write a maintainable loop for my production system". My answer works whether you use 5 or you write j = jSize ; i = iSize. Whether you want to use it or not is your choice.Intermarry
@Intermarry You're right, the answer is a valid answer. It's just bad programming style as it currently is, that is why it is not suitable for production code, as you admit yourself. q.e.d. That is worth to be pointed out for novice programmers who do not see this as obviously. I dare to say that most people come to SO for advice. We want to give them good advice ;)Firehouse
Thanks for your approval...Intermarry
S
24
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
            }
        }
    }

code copied from Best way to break from nested loops in Javascript?

Please search before posting a question. The link was the FIRST related question I saw on the left side of this page!

Squireen answered 14/10, 2009 at 7:54 Comment(0)
D
11

Unfortunately you'll have to set a flag or use labels (think old school goto statements)

var breakout = false;

for(i=0;i<5;i++)
{
    for(j=i+1;j<5;j++)
    {
        breakout = true;
        break;
    }
    if (breakout) break;
    alert(1)
};

The label approach looks like:

end_loops:
for(i=0;i<5;i++)
{
    for(j=i+1;j<5;j++)
    {
        break end_loops;
    }
    alert(1)
};

edit: label incorrectly placed.

also see:

Dorsett answered 14/10, 2009 at 7:47 Comment(1)
So the label can't go downstream of the break correct? Like lets say okay some condition was met I don't need the loops at all. Can a branch to a label declared after the loops be made?Jacob
M
6

In my opinion, it's important to keep your construct vocabulary to a minimum. If I can do away with breaks and continues easily, I do so.

function foo ()
{
    var found = false;
    for(var k = 0; (k < 4 && !found); k++){
        for(var m = 0; (m < 4 && !found); m++){
           if( m === 2){
               found = true;
           }
        }
    }
    return found;
}

Be warned, after the loop, m and k are one larger that you might think. This is because m++ and k++ are executed before their loop conditions. However, it's still better than 'dirty' breaks.

EDIT: long comment @Dennis...

I wasn't being 100% serious about being 'dirty', but I still think that 'break' contravenes my own conception of clean code. The thought of having multi-level breaks actually makes me feel like taking a shower.

I find justifying what I mean about a feeling about code because I have coded all life. The best why I can think of it is is a combination of manners and grammar. Breaks just aren't polite. Multi level breaks are just plain rude.

When looking at a for statement, a reader knows exactly where to look. Everything you need to know about the rules of engagement are in the contract, in between the parenthesis. As a reader, breaks insult me, it feels like I've been cheated upon.

Clarity is much more respectful than cheating.

Marcenemarcescent answered 4/6, 2011 at 10:7 Comment(5)
Why should you need to keep your construct vocab to a minimum? The argument that breaks are 'dirty' is absurd. In terms of readability, your solution is much worse, and it performs no better. You have a point though, like any construct, breaks can be abused, but a bit of cheating here or there for readability purposes is definitely okay.Beadroll
too long to fit into a comment to i did an edit.Marcenemarcescent
Also, keeping construct vocabulary to a minimum is more of a result of switching between many languages frequently. You tend to use more language that is common between them. In the case of JavaScript, this has the benefit of making the code compatible across systems and also benefits readers who may not use JavaScript as their primary language.Marcenemarcescent
+1 for a different approach. It's good to have optionsTartary
adding the test in two loops is more likely to cause errors than a break or continue. In this case, you can simply return when you find a matchPouliot
R
5

Use function for multilevel loops - this is good way:

function find_dup () {
    for (;;) {
        for(;;) {
            if (done) return;
        }
    }
}
Rashida answered 14/10, 2009 at 9:16 Comment(2)
Wooo, what the heck is for(;;)? Never seen that before.Greenes
Infinity loop :) it's like while (true) {}Rashida
Q
3

Wrap in a self executing function and return

(function(){
    for(i=0;i<5;i++){
        for (j=0;j<3;j++){
            //console.log(i+' '+j);
            if (j == 2) return;
        }
    }
})()
Quartered answered 21/5, 2014 at 23:26 Comment(0)
L
1

You return to "break" you nested for loop.

function foo ()
{
    //dance:
    for(var k = 0; k < 4; k++){
        for(var m = 0; m < 4; m++){
            if(m == 2){
                //break dance;
                return;
            }
        }
    }
}
foo();
Loquacious answered 17/7, 2015 at 8:29 Comment(1)
This exits the entire function rather than just breaking the loop.Altamirano
S
-1

break doesn't take parameters. There are two workarounds:

  1. Wrap them in a function and call return

  2. Set a flag in the inner loop and break again right after the loop if the flag is set.

Supralapsarian answered 14/10, 2009 at 7:47 Comment(2)
Actually, it does take parameters. :) developer.mozilla.org/en/Core_JavaScript_1.5_Reference/…Hoof
Aaron: I just tested in IE6; it does :)Essam
M
-1

Break 1st loop:

for(i=0;i<5;i++)
{
  for(j=i+1;j<5;j++)
  {
    //do something

    break;
  }
  alert(1);
};

Break both loops:

for(i=0;i<5;i++)
{
  var breakagain = false;
  for(j=i+1;j<5;j++)
  {
    //do something

    breakagain = true;
    break;
  }
  alert(1);
  if(breakagain)
    break;
};
Meliorate answered 14/10, 2009 at 7:48 Comment(0)
T
-1

You can break nested for loops with the word 'break', it works without any labels.

In your case you need to have a condition which is sufficient to break a loop.

Here's an example:

var arr = [[1,3], [5,6], [9,10]];
for (var a = 0; a<arr.length; a++ ){
  for (var i=0; i<arr[a].length; i++) {
    console.log('I am a nested loop and i = ' + i);
    if (i==0) { break; }
  }
  console.log('first loop continues');
}

It logs the following:

> I am a nested loop and i = 0 
> first loop continues
> I am a nested loop and i = 0 
> first loop continues
> I am a nested loop and i = 0 
> first loop continues

The return; statement does not work in this case. Working pen

Troubadour answered 10/6, 2017 at 21:24 Comment(0)
H
-9
function myFunction(){
  for(var i = 0;i < n;i++){
    for(var m = 0;m < n;m++){
      if(/*break condition*/){
        goto out;
      }
    }
  }
out:
 //your out of the loop;
}
Hydatid answered 14/10, 2009 at 7:55 Comment(4)
In Javascript, "goto" may be a reserved word, but it doesn't actually do anything...Shakhty
Downvoted, same reason as NickFitz.Cullum
@NickFitz, nope, goto is not a reserved word in JavaScript: ReferenceError: goto is not definedGreenes
@Derek朕會功夫 It's a "future reserved word" (in some ECMAScript standards), i.e. it's not implemented yet but might be in the future.Capitulary

© 2022 - 2024 — McMap. All rights reserved.