Какой лучший способ избавиться от вложенных циклов в JavaScript? - PullRequest
362 голосов
/ 08 октября 2008

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

//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 + "</a> : ");
            break; // <---HERE, I need to break out of two loops.
         }
      }
   }
}

Ответы [ 14 ]

857 голосов
/ 08 октября 2008

Так же, как Perl,

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, эти метки могут использоваться только для continue и break, поскольку Javascript не имеет goto.

143 голосов
/ 08 октября 2008

Оберните это в функцию, а затем просто return.

75 голосов
/ 08 апреля 2009

Я немного опаздываю на вечеринку, но ниже представлен подход, не зависящий от языка, который не использует GOTO / метки или перенос функций:

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. С другой стороны, внутренний цикл должен завершить текущую итерацию перед завершением, поэтому он может быть неприменим в некоторых сценариях.

66 голосов
/ 01 ноября 2013

Я понимаю, что это действительно старая тема, но поскольку моего стандартного подхода еще нет, я решил опубликовать его для будущих гуглеров.

var a, b, abort = false;
for (a = 0; a < 10 && !abort; a++) {
    for (b = 0; b < 10 && !abort; b++) {
        if (condition) {
            doSomeThing();
            abort = true;
        }
    }
}
39 голосов
/ 08 октября 2008
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
}

Как это? :)

32 голосов
/ 16 июля 2009

довольно просто

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;}
}
14 голосов
/ 11 мая 2015

Как насчет использования без перерывов, без флагов отмены и без дополнительных проверок условий. Эта версия просто взрывает переменные цикла (делает их Number.MAX_VALUE) при выполнении условия и принудительно завершает все циклы.

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

Был найден аналогичный ответ для вложенных циклов убывающего типа, но это работает для вложенных циклов инкрементного типа без необходимости учитывать значение завершения каждого цикла для простых циклов.

Другой пример:

// 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
        }
      }
    }
  }
}
6 голосов
/ 31 декабря 2018

Вот пять способов вырваться из вложенных циклов в JavaScript:

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

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

2) Использовать ярлык

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

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();
5 голосов
/ 26 сентября 2017

Как насчет того, чтобы подтолкнуть петли к их предельным пределам

    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;
            }
         }
       }
     }
3 голосов
/ 10 августа 2015

Если вы используете Coffeescript, есть удобное ключевое слово «do», которое упрощает определение и немедленное выполнение анонимной функции:

do ->
  for a in first_loop
    for b in second_loop
      if condition(...)
        return

... так что вы можете просто использовать «return» для выхода из циклов.

...