2008-10-08 169 views
274

JavaScript中嵌套循環的最佳方式是什麼?在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. 
     } 
     } 
    } 
} 

回答

664

就像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不同,這些標籤只能用於continuebreak,因爲Javascript沒有goto

+0

有趣!我沒有意識到你可以打破標籤。 – 2008-10-08 15:09:56

+5

它是「打破」*標籤「嗎?它看起來更像是你用n個可選嵌套循環命名一個塊,然後通過調用break {label}來中止「遍歷塊」。 – 2011-12-08 15:17:04

+6

@NielsBom你是對的:它打破了給定標籤的循環。它不會「轉到」標籤。你本質上是命名一個循環,並說我想跳出一個循環。 – devios1 2012-05-31 21:50:01

110

總結,最多的功能,然後就return

+0

I'我不是提問者,但我的猜測是這很容易? ephemient's也同樣有效,儘管在語法上我不喜歡這樣的標籤。感覺有點像GOTO - 雖然我不想在這裏打開這種蠕蟲。 – swilliams 2008-10-08 19:36:30

+9

我選擇接受這個答案,因爲它很簡單,可以以優雅的方式實現。我絕對討厭GOTO,並認爲他們不好的做法(*可以打開*),Ephemient的離得太近了。 ; o) – 2008-10-08 20:05:25

+12

國際海事組織,GOTO's都可以,只要他們不破壞結構。但是對於他們自己! – ephemient 2008-10-10 20:09:09

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

那是怎麼回事? :)

+2

我想這是什麼swilliams得到 – 2008-10-08 20:13:55

+0

謝謝你明確這樣拼寫出來。我總是忘記我可以將任意一段代碼封裝在一個匿名函數中,然後調用它。 – Emily 2011-01-04 16:31:16

+17

如果循環很大,這會增加很大的運行時間成本 - 必須通過Javascript解釋器/編譯器(或者「compreter」)創建一個新的函數執行上下文(並且在某些時候由GC釋放) ) 每一次。 – 2011-10-18 12:29:04

65

我有點遲到了,但下面是一個語言無關的方法不使用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人羣。不利的一面是,內部循環需要在終止之前完成當前迭代,因此在某些情況下可能不適用。

30

很簡單

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

我意識到這是一個真正的老話題,但因爲我的標準的方法還沒有實現,我想我將它張貼在未來的Google。

var a, b, abort = false; 
for (a = 0; a < 10 && !abort; a++) { 
    for (b = 0; b < 10 && !abort; b++) { 
     if (condition) { 
      doSomeThing(); 
      abort = true; 
     } 
    } 
} 
11

如何使用沒有休息可言,沒有放棄的標誌,並沒有多餘的條件檢查。當條件滿足時,這個版本只會發送循環變量(使它們爲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 
     } 
     } 
    } 
    } 
} 
3

如果使用CoffeeScript中,有一個方便的「做」的關鍵字,可以更容易定義和立即執行的匿名函數:

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

...所以你可以簡單地使用「返回」來擺脫循環。

2

我想我會展示一個函數式編程方法。你可以跳出嵌套的Array.prototype.some()和/或Array.prototype.every()函數,就像我的解決方案一樣。這種方法的另一個好處是Object.keys()只枚舉一個對象自己的枚舉屬性,而"a for-in loop enumerates properties in the prototype chain as well"

關閉到OP的溶液:

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 + "</a> : "); 
        return true; 
       } 
      }); 
     }); 

     return res; 
    } 

解決方案,降低遍歷標題/項目:

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 + "</a> : "); 
      remainingArgs.splice(i, 1); 

      if (remainingArgs.length === 0) 
       return true; 
      } 
     }); 
    }); 
-3

最好的辦法是 -
1)分類的兩個陣列,其被用於在第一和第二回路中。
2)如果項目匹配,則打破內部循環並保持索引值。
3)當開始下一次迭代時啓動內部循環並保持索引值。

-1

我知道這是8年前提出,但在ES6我們得到了for...of循環從而能夠使用的標準突破功能:

for (let item of items) { 
    if (item.id === id) { 
    //do something cool 
    break; 
    } 
} 
1

如何推動循環到他們的最終極限

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; 
      } 
     } 
     } 
    } 
相關問題