Как разбить вложенные циклы в JavaScript?

Я пробовал это:

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

только чтобы получить:

SyntaxError: отсутствует ; перед оператором

Итак, как мне разорвать вложенный цикл в JavaScript?


person Mask    schedule 14.10.2009    source источник
comment
перерыв (2); : o что вы имеете в виду под 2, break не может иметь аргументов   -  person Rakesh Juyal    schedule 14.10.2009
comment
В строке 7 отсутствует точка с запятой после alert(1).   -  person Nathan Taylor    schedule 14.10.2009
comment
@Nathan Taylor: точка с запятой в JavaScript не обязательна, но считается хорошим стилем   -  person Tim Büthe    schedule 14.10.2009
comment
Почти дубликат stackoverflow.com/q/183161/149391   -  person Joey Adams    schedule 13.06.2012
comment
@RakeshJuyal это на других языках, таких как C   -  person Masadow    schedule 04.02.2015


Ответы (15)


Вы должны иметь возможность разбить ярлык, например:

function foo () {
    dance:
    for (var k = 0; k < 4; k++) {
        for (var m = 0; m < 4; m++) {
            if (m == 2) {
                break dance;
            }
        }
    }
}
person Noon Silk    schedule 14.10.2009
comment
брейк данс хар хар - person ahnbizcad; 13.05.2020
comment
Также существует тот факт, что JS требует участия этого гиганта dance. Другие языки дают вам break (буквально, как break 2). - person i336_; 16.03.2021

Вам нужно назвать внешний цикл и разорвать его, а не внутренний цикл - вот так.

outer_loop: 
for(i=0;i<5;i++) {
    for(j=i+1;j<5;j++) {
        break outer_loop;
    }
    alert(1);
}
person Fenton    schedule 14.10.2009
comment
Вау, я не знал, что мы можем давать названия петлям, отличная информация! +1 - person o.k.w; 14.10.2009
comment
@ o.k.w: вы не называете цикл. Вы просто обозначаете позицию в источнике. - person xtofl; 14.10.2009
comment
Никогда не знал, что JavaScript поддерживает ярлыки. Интересно, почему я никогда раньше этого не видел. : O - person Nathan Taylor; 14.10.2009
comment
@xtofl: Не совсем так. Вы связываете метку с оператором (который может быть циклом), помещая его непосредственно перед. Это полезно только с оператором блока, поскольку метка доступна только с операторами break и continue внутри блока. - person Tim Down; 14.10.2009
comment
@Nathan: вероятно, потому что это очень плохая практика: если вам нужно использовать метки в вашем коде, это знак того, что вам нужно переписать свой код ;-) - person NickFitz; 14.10.2009
comment
@NickFitz: вы могли бы привести аргумент в пользу производительности. В случае вложенных циклов метки могут быть полезны для выхода из внешнего цикла. Хотя он может быть более элегантным и модульным, чтобы избежать вложенных циклов, перемещая внутренние циклы для разделения функций, он будет работать немного медленнее из-за дополнительных вызовов функций. - person Tim Down; 14.10.2009
comment
ярлыки являются причиной того, что что-то вроде onclick:"javascript: doThis()" не вызывает ошибки. javascript: в этом случае считается ненужным ярлыком. - person Juan Mendes; 29.12.2012

См. Аарона. В противном случае: j=5;i=5 вместо break.

person Glenn    schedule 14.10.2009
comment
Это просто лучшее и самое чистое решение. Не возвращайтесь к этикеткам, они ужасно выглядят. - person Pedro Moreira; 08.08.2014
comment
Это уродливо. for(i=0;i<5;i++) предполагается запустить 5 раз. Обновление i вне оператора цикла заставляет его вести себя неожиданным образом. - person Florian F; 12.11.2014
comment
Уродливое - это субъективно. Предполагается, что цикл запускается столько раз, сколько вы хотите. Вопрос заключался в том, как разорвать двойной цикл for, поскольку ни j, ни i не достигают 5. Единственная техническая причина для предпочтения моего и брейк-данса - это случай, когда вы хотите, чтобы i / j показывал завершение (== 5) vs незавершенность (== ‹5) пост-петель. - person Glenn; 13.11.2014
comment
Согласитесь с @FlorianF, это уродливо в том смысле, что это кажется более подверженным ошибкам решением, чем добавление метки, хотя у меня нет никаких статистических доказательств этого. Независимо от того, привыкли ли вы к ярлыкам или нет, они, конечно, не безошибочная концепция, но жесткие коды кодирования, которые вы должны изменить в нескольких местах, если одно из них изменится, - это ужасный стиль программирования. Что касается оценки, это справедливое заявление, помогающее определить лучший ответ для OP. - person Manuel; 24.04.2020
comment
@Manuel: re: ужасный стиль программирования. Вы можете использовать константы и т. Д. Для чисел в обоих местах, но это не имеет отношения к вопросу. Поскольку на этот вопрос был дан ответ в 2009 году, сегодня я бы сказал, что вам следует переписать свой код, чтобы не использовать цикл for. (фильтровать, уменьшать, отображать и т. д.) - person Glenn; 28.04.2020
comment
@Glenn, вопрос в том, как разорвать цикл for, поэтому ответ актуален и сегодня, независимо от доступности функций более высокого порядка. Если добавление дополнительного объявления var необходимо, чтобы сделать этот ответ практически осуществимым, его следует добавить к ответу, чтобы раскрыть всю сложность. Практичность, ремонтопригодность, сложность - ключевые факторы при оценке ответа. - person Manuel; 28.04.2020
comment
@Manuel есть разница между производственным кодом и пониманием того, как что-то работает. Вопрос в том, как выйти из вложенных циклов, а не в том, как написать поддерживаемый цикл для моей производственной системы. Мой ответ работает независимо от того, используете ли вы 5 или пишете j = jSize; i = iSize. Хотите ли вы использовать это или нет - ваш выбор. - person Glenn; 29.04.2020
comment
@Glenn Вы правы, ответ правильный. Это просто плохой стиль программирования в нынешнем виде, поэтому он не подходит для продакшена, как вы сами признаете. q.e.d. На это стоит обратить внимание начинающим программистам, которые не видят в этом очевидности. Осмелюсь сказать, что большинство людей обращаются в SO за советом. Мы хотим дать им хороший совет;) - person Manuel; 29.04.2020
comment
Спасибо за одобрение ... - person Glenn; 29.04.2020

Есть как минимум пять разных способов выйти из двух или более петель:

1) Установить родительский цикл в конец

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

2) Используйте ярлык

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

3) Используйте переменную

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) Использовать самоисполняющуюся функцию

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

5) Используйте обычную функцию

function nested_loops()
{
    for (i = 0; i < 5; i++)
    {
        for (j = 0; j < 5; j++)
        {
             if (j === 2)
                 return;
        }
    }
}
nested_loops();
person Dan Bray    schedule 05.08.2018
comment
Весь смысл многоуровневого перерыва в том, чтобы избежать №3. - person Wyck; 24.10.2019

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
            }
        }
    }

код скопирован из Лучший способ выйти из вложенных циклов в Javascript?

Пожалуйста, поищите перед тем, как задать вопрос. Ссылка была ПЕРВЫМ вопросом, который я увидел в левой части страницы!

person Jim    schedule 14.10.2009

К сожалению, вам придется установить флаг или использовать ярлыки (подумайте о старых инструкциях goto)

var breakout = false;

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

Подход с использованием этикеток выглядит так:

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

изменить: метка размещена неправильно.

также см:

person Jonathan Fingland    schedule 14.10.2009
comment
Значит, этикетка не может идти за разрывом, правильно? Скажем так, хорошо, какое-то условие было выполнено, мне вообще не нужны циклы. Можно ли сделать переход к метке, объявленной после циклов? - person eaglei22; 12.07.2017

На мой взгляд, важно сводить словарный запас по конструктам к минимуму. Если я могу избавиться от перерывов и легко продолжу, я так и сделаю.

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;
}

Имейте в виду, что после цикла m и k на единицу больше, чем вы могли подумать. Это потому, что m ++ и k ++ выполняются до своих условий цикла. Однако это все же лучше, чем «грязные» перерывы.

РЕДАКТИРОВАТЬ: длинный комментарий @Dennis ...

Я не на 100% серьезно относился к тому, чтобы быть «грязным», но я все же считаю, что «перерыв» противоречит моей собственной концепции чистого кода. Мысль о многоуровневых перерывах на самом деле вызывает у меня желание принять душ.

Я считаю оправданным то, что я имею в виду под чувством кода, потому что я программировал всю жизнь. Лучшее, что я могу придумать, - это сочетание манер и грамматики. Перерывы просто не вежливы. Многоуровневые перерывы - это просто грубость.

Глядя на оператор for, читатель точно знает, где искать. Все, что вам нужно знать о правилах участия, заключено в контракте между скобками. Меня, как читателя, оскорбляют, такое ощущение, что меня обманули.

Ясность гораздо более уважительна, чем обман.

person thomas-peter    schedule 04.06.2011
comment
Почему вам нужно сводить свой словарный запас к минимуму? Аргумент, что брейки «грязные», абсурден. С точки зрения удобочитаемости ваше решение намного хуже и работает не лучше. Хотя у вас есть смысл, как и любой другой конструкцией, перерывами можно злоупотреблять, но немного обмана здесь или там для удобства чтения - это определенно нормально. - person Dennis; 11.07.2012
comment
слишком долго, чтобы поместиться в комментарий, чтобы я отредактировал. - person thomas-peter; 13.07.2012
comment
Кроме того, сокращение словарного запаса конструктов до минимума является результатом частого переключения между многими языками. Вы склонны использовать больше общего между ними языка. В случае с JavaScript это дает то преимущество, что делает код совместимым между системами, а также приносит пользу читателям, которые не могут использовать JavaScript в качестве основного языка. - person thomas-peter; 13.07.2012
comment
+1 за другой подход. Хорошо иметь варианты - person Phil Strong; 30.08.2012
comment
добавление теста в два цикла с большей вероятностью вызовет ошибки, чем break или continue. В этом случае вы можете просто вернуться, когда найдете совпадение. - person Juan Mendes; 29.12.2012

Используйте функцию для многоуровневых циклов - это хороший способ:

function find_dup () {
    for (;;) {
        for(;;) {
            if (done) return;
        }
    }
}
person Anatoliy    schedule 14.10.2009
comment
Wooo, что, черт возьми, for(;;)? Никогда раньше такого не видел. - person Derek 朕會功夫; 25.02.2012
comment
Бесконечный цикл :) это как в то время как (правда) {} - person Anatoliy; 25.02.2012

Оберните самоисполняющуюся функцию и верните

(function(){
    for(i=0;i<5;i++){
        for (j=0;j<3;j++){
            //console.log(i+' '+j);
            if (j == 2) return;
        }
    }
})()
person kehers    schedule 21.05.2014

Вы return, чтобы "разорвать" вложенный вами for цикл.

function foo ()
{
    //dance:
    for(var k = 0; k < 4; k++){
        for(var m = 0; m < 4; m++){
            if(m == 2){
                //break dance;
                return;
            }
        }
    }
}
foo();
person GibboK    schedule 17.07.2015
comment
Это завершает работу всей функции, а не просто разрывает цикл. - person Sebastian Simon; 02.03.2018

Вы можете разорвать вложенные циклы for с помощью слова "break", это работает без каких-либо ярлыков.

В вашем случае вам нужно иметь условие, достаточное для разрыва цикла.

Вот пример:

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');
}

Он регистрирует следующее:

> 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

Оператор return; в этом случае не работает. Рабочая ручка

person Ilya Kushlianski    schedule 10.06.2017

Другой трюк - настроить родительский цикл так, чтобы он достиг конца, а затем прервал текущий цикл.

function foo()
{
    for(var k = 0; k < 4; k++){
        for(var m = 0; m < 4; m++){
            if(m == 2){
                k = 5; // Set this then break
                break;
            }
          console.log(m);
        }
    }
}
person StefansArya    schedule 30.01.2018

break не принимает параметров. Есть два обходных пути:

  1. Оберните их в функцию и вызовите return

  2. Установите флаг во внутреннем цикле и снова прервите цикл сразу после цикла, если этот флаг установлен.

person Aaron Digulla    schedule 14.10.2009
comment
Фактически, он принимает параметры. :) developer.mozilla.org/en/Core_JavaScript_1.5_Reference/ - person deceze♦; 14.10.2009
comment
Аарон: Я только что тестировал в IE6; оно делает :) - person Noon Silk; 14.10.2009

Разрыв 1-й петли:

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

    break;
  }
  alert(1);
};

Обе петли оборвать:

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;
};
person o.k.w    schedule 14.10.2009

person    schedule
comment
В Javascript goto может быть зарезервированным словом, но на самом деле оно ничего не делает ... - person NickFitz; 14.10.2009
comment
Проголосовали против по той же причине, что и NickFitz. - person Tim Down; 14.10.2009
comment
@NickFitz, нет, goto не является зарезервированным словом в JavaScript: ReferenceError: goto is not defined - person Derek 朕會功夫; 25.02.2012
comment
@Derek 朕 會 功夫 Это будущее зарезервированное слово (в некоторых стандартах ECMAScript), т.е. он еще не реализован, но может появиться в будущем. - person JJJ; 24.01.2014