2012-10-14 78 views
5

低於for循環執行javascsript交替向前和向後

我試圖做的是通過塊迭代一個數組,從塊交替迭代的方向塊更新。困惑?我也是如此。例如,如果我想循環通過一個包含25個元素的數組,但我想按照以下順序執行操作:0,1,2,3,4,9,8,7,6,5,10 ,11,12,13,14,19,18,17,16,15,20,21,22,23,24,這樣做最有效的方法是什麼?我正在尋找可伸縮的東西,因爲我現在正在使用的數組實際上是225個元素,我想用15個元素塊來遍歷它,但這可能會在某些時候改變。到目前爲止,我發現唯一實際工作的方法是將迭代順序硬連線到第二個數組,然後以正常方式遍歷該數組,以獲取原始數組的索引。但這很糟糕。任何幫助將不勝感激。

@Bergi問一些示例代碼。請不要毆打我太多。我仍然是一個新手:

function zeroPadNumber(theNumber, thePadding) { 
    var thePaddedNumber = thePadding.substring(0, (thePadding.length - theNumber.length)) + theNumber; 
    return thePaddedNumber; 
} 

var thisTile = 225; 
var waveLoop = 15; 
function mosaicWave() { 
    var theStartNum = thisTile; 
    for (w = 0; w < 15; w++) { 
     var theNum = theStartNum - w; 
     var theNumString = String(theNum); 
     var thePaddedNum = zeroPadNumber(theNumString, "000"); 
     var theImgName = "sm_" + thePaddedNum; 
     var theNewSrc = theImgFolder + theImgName + "bg.gif"; 
     document.images[theImgName].src = theNewSrc; 
     thisTile = theNum - 1; 
     if (waveLoop < 15) { 
      var prevStartTile = theStartNum + 15; 
      var thePrevNum = prevStartTile - w; 
      var thePrevNumString = String(thePrevNum); 
      var thePrevPaddedNum = zeroPadNumber(thePrevNumString, "000"); 
      var thePrevName = "sm_" + thePrevPaddedNum; 
      var thePrevSrc = theImgFolder + thePrevName + ".gif"; 
      document.images[thePrevName].src = thePrevSrc; 
     } 
    } 
    if (waveLoop == 1) { 
     var lastWave = function() { 
      var theStartNum = 15; 
      for (c = 0; c < 15; c++) { 
       var theNum = theStartNum - c; 
       var theNumString = String(theNum); 
       var thePaddedNum = zeroPadNumber(theNumString, "000"); 
       var theImgName = "sm_" + thePaddedNum; 
       var theNewSrc = theImgFolder + theImgName + ".gif"; 
       document.images[theImgName].src = theNewSrc; 
      } 
     } 
     setTimeout(lastWave, 100); 
     waveLoop = 15; 
     thisTile = 225; 
    } else { 
     waveLoop--; 
     setTimeout(mosaicWave, 100); 
    } 
} 

這段代碼做了一個不同的動畫。它從矩陣的右下角開始,並「打開」底部行中的15個瓦片。然後它向上移動一行,打開該行中的瓷磚並關閉前一行中的瓷磚。等到頂行開啓然後關閉。真正從我試圖在新功能中實現的自頂向下的蛇形效果不那麼遠。在每一排上的倒車順序是主要的東西絆倒我。話雖如此,有關優化上述代碼的任何建議也將不勝感激。

更新1:

對我來說,這似乎像它應該工作,但事實並非如此。任何人都可以發現問題嗎?

var loopRange = 225; 
var blockRange = 15; 
var theDirection = 1; 
var weaveLoop = 0; 

function mosaicWeave() { 
    var curObj, curSrc, lastObj, lastSrc; 
    var toggleLeadTile = function() { 
     alert(curSrc); 
     curObj.src = curSrc; 
    }; 
    var toggleLastTile = function() { 
     lastObj.src = lastSrc; 
    }; 
    while (weaveLoop < loopRange) { 
     imgNum = weaveLoop + 1; 
     imgName = "sm_" + zeroPadNumber(String(imgNum), "000"); 
     if (imgNum < 15) { 
      //handle first row 
      curObj = document.images[imgName]; 
      curSrc = theImgFolder + imgName + "bg.gif"; 
      window.setTimeout(toggleLeadTile, 100); 
     } else if (imgNum == 225) { 
      //handle last row 
      curObj = document.images[imgName].src; 
      curSrc = theImgFolder + imgName + "bg.gif"; 
      window.setTimeout(toggleLeadTile, 100); 
      for (i = 211; i < 226; i++) { 
       lastImgName = "sm_" + ((weaveLoop + 1) - 15); 
       lastObj = document.images[lastImgName]; 
       lastSrc = theImgFolder + lastImgName + ".gif"; 
       window.setTimeout(toggleLastTile, 100); 
      } 
     } else { 
      //handle middle rows 
      lastImgName = "sm_" + ((weaveLoop + 1) - 15); 
      curObj = document.images[imgName]; 
      curSrc = theImgFolder + imgName + "bg.gif"; 
      lastObj = document.images[lastImgName]; 
      lastSrc = theImgFolder + lastImgName + ".gif"; 
      window.setTimeout(toggleLeadTile, 100); 
      window.setTimeout(toggleLastTile, 100); 
     } 
     if (weaveLoop % blockRange == (theDirection == -1 ? 0 : blockRange - 1)) { 
      theDirection *= -1; 
      weaveLoop += blockRange; 
     } else { 
      weaveLoop += theDirection; 
     } 
    } 
} 

更新2:

感謝大家的輸入。這工作:

var resetLoop = 1; 
var weaveArray = new Array(225); 
var weaveRange = 15, weaveDirection = 1, weaveIndex = 0, wInitLoop = 0; 

function mosaicWeave() { 
    while (weaveIndex < 225) { 
     weaveArray[wInitLoop] = weaveIndex + 1; 
     if (weaveIndex % weaveRange == (weaveDirection == -1 ? 0 : weaveRange - 1)) { 
      weaveDirection *= -1; 
      weaveIndex += weaveRange; 
     } else { 
      weaveIndex += weaveDirection; 
     } 
     wInitLoop++; 
    } 
    mWeaveOn(); 
} 

function mWeaveOff() { 
    var theNumString = String(weaveArray[resetLoop - 16]); 
    var theImgName = "sm_" + zeroPadNumber(theNumString, "000"); 
    document.images[theImgName].src = "images/" + theImgName + ".gif"; 
    mosaicArray[resetLoop - 1] = 0; 
    resetLoop++; 
    if (resetLoop < 226) { 
     setTimeout(mWeaveOn, 25); 
    } else if (resetLoop > 225 && resetLoop <= 240) { 
      setTimeout(mWeaveOff, 25); 
    } else { 
     resetLoop = 1; 
    } 
} 

function mWeaveOn() { 
    var theNumString = String(weaveArray[resetLoop - 1]); 
    var theImgName = "sm_" + zeroPadNumber(theNumString, "000"); 
    document.images[theImgName].src = "images/" + theImgName + "bg.gif"; 
    mosaicArray[resetLoop - 1] = 1; 
    if (resetLoop < 16) { 
     resetLoop++; 
     setTimeout(mWeaveOn, 25); 
    } else { 
     setTimeout(mWeaveOff, 25); 
    } 
} 

有沒有人有意見,如果有一個更有效的方式做到這一點?或者在不同的平臺/瀏覽器或不同環境下討論這可能會如何破解?再次感謝。

回答

0

該函數接受陣列和塊大小(在示例中,5)

function forwardAndBack(arr, blocksize){ 
    var i, j, l = arr.length ; 
    for (i = 0 ; i < l ; i++){ 
    if (i % (2 * blocksize) > (blocksize - 1)){ 
     j = i + (blocksize - (2*(i % blocksize)))-1 ; 
    } 
    else { 
     j = i ; 
    } 
    arr[j] && myFunction(arr[j]) ; // In case you've gone too high 
    } 
} 

像這樣來使用:

var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] ; 
var result = [] ; 
function myFunction(x){result.push(x)} ; 

forwardAndBack(arr, 5); 

console.log(result) ; // returns [0, 1, 2, 3, 4, 9, 8, 7, 6, 5, 10, 11, 12, 13, 14, 19, 18, 17, 16, 15, 20, 21, 22, 23, 24] 
2

這是一種靈活的解決方案,其中可以改變塊大小爲你需要它。

var index, max = 25; 
for (var i = 0; i < max; i++) { 
    if (parseInt(i/5) % 2) 
    index = parseInt(i/5)*5 + 4 - i % 5; 
    else 
    index = i; 
    // use index as array index 
    foo(index); 
} 

Fiddle

如果你始終五的倍數,你可以硬編碼在五行迭代,做一個外環,其對以max/5並切換到合適的硬編碼的迭代。

var index, max = 25; 
for (var i=0; i<max/5; i++) { 
    if (i%2) { 
    foo(i*5+4); 
    foo(i*5+3); 
    foo(i*5+2); 
    foo(i*5+1); 
    foo(i*5+0); 
    } else { 
    foo(i*5+0); 
    foo(i*5+1); 
    foo(i*5+2); 
    foo(i*5+3); 
    foo(i*5+4); 
    } 
} 

Fiddle

4
var arr = [0,1,2,3,4,5,6,7,8,9,10,11,11,13,14,15,16,17,18,19,20,21,22,23,24], 
    i = 0, 
    j = arr.length, 
    tmp, 
    chunk = 5; 

while(i < j) { 
    tmp = arr.slice(i, i+=chunk); 
    if ((i/chunk) % 2 == 0) { 
     tmp = tmp.reverse(); 
    } 
    console.log(tmp); 
} 

​The demo.

1

我想最簡單和最清晰的解決方法是窩2個洛斯:

var arr = new Array(25), 
    chunksize = 5; 
for (var i=0; i<arr.length; i+=chunksize) 
    if (i % (chunksize*2)) 
     for (var j=i+chunksize-1; j>=i; j--) 
      exec(j); 
    else 
     for (var j=i; j<i+chunksize; j++) 
      exec(j); 

但是,您也可以只使用一個循環和loopcounter。在正確的點(4,5,14,15,...)中,方向(增量/減量)會改變,並且計數器跳躍一個塊(4→9,5→10,14→19,...):

var arr = new Array(25), 
    chunksize = 5; 

var dir = 1, 
    i = 0; 
while (i<arr.length) { 
    exec(i); // or whatever you need to do 
    if (i % chunksize == (dir==-1 ? 0 : chunksize - 1)) { 
     dir *= -1; 
     i += chunksize; 
    } else 
     i += dir; 
} 

,或者在一個語句:

for (var dir=1, i=0; i<arr.length; i+= (i+1)%chunksize == (dir==-1) ? (dir*=-1) && chunksize : dir) 
    exec(i); // or whatever you need to do 
+0

你可以添加一些背景到您的文章?這個想法是什麼? –

+0

我用一個計數器做了一個循環。在右點(4,5,14,15,...)中,方向(遞增/遞減)改變並且計數器跳轉一個塊大小(4→9,5→10,14→19,...) – Bergi

+0

我有一個矩陣15 x 15格的小圖片。每個圖像有兩個版本(開啓和關閉狀態)。我想以蛇形方式對每一個進行簡單的圖像交換(第1行:從左到右,第2行:從右到左,第3行:從左到右等)。在第一行圖像「打開」之後,會有一個額外的皺紋,它們將以相同的順序「關閉」,而第二行中的圖像「打開」。這是現在的網站:[uglydigits.com](http://www.uglydigits.com/index.html)我試圖實現的蛇形效果將用於重置功能。 –