2012-10-14 8 views
5

BELOWjavascsript for-Schleife auszuführen abwechselnd vorwärts und rückwärts

AKTUALISIERT Was ich versuche ist in Chunks durch ein Array iterieren zu tun ist, um die Richtung der Iteration von Chunk chunk abwechselt. Verwirrt? Ich bin es auch. Zum Beispiel, wenn ich ein Array mit 25 Elementen durchlaufen möchte, aber ich möchte es in dieser Reihenfolge tun: 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, was wäre der effizienteste Weg, dies zu tun? Ich suche nach etwas Skalierbarem, weil das Array, mit dem ich gerade arbeite, tatsächlich 225 Elemente enthält und ich es in 15 Elementbrocken durchqueren möchte, aber das kann sich irgendwann ändern. Bis jetzt ist die einzige Methode, die ich herausgefunden habe, die tatsächlich funktioniert, die Iterationsreihenfolge in ein zweites Array zu verdrahten und dann auf die normale Art und Weise durchzulaufen, um die Indizes für das ursprüngliche Array zu erhalten. Aber das ist scheiße. Jede Hilfe würde sehr geschätzt werden.

@Bergi fragte nach einem Beispielcode. Bitte verprüg mich nicht zu sehr. Ich bin immer noch ein Noob:

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

Dieses Snippet macht eine andere Animation. Es beginnt in der unteren rechten Ecke der Matrix und "schaltet" die 15 Kacheln in der unteren Reihe ein. dann bewegt es sich eine Reihe weiter, dreht die Kacheln in dieser Reihe an und schaltet die Kacheln in der vorherigen Reihe aus. Und so weiter, bis die oberste Reihe an und dann ausgeschaltet wird. nicht wirklich weit weg vom Top-Down-Serpentine-Effekt, den ich in der neuen Funktion zu erreichen versuche. Die umgekehrte Reihenfolge in jeder Reihe war die Hauptsache, die mich stürzte. Davon abgesehen würden auch Vorschläge zur Optimierung des obigen Codes sehr geschätzt werden.

UPDATE 1:

Mir scheint dies wie sollte es funktionieren, aber es funktioniert nicht. Kann jemand das Problem erkennen?

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

UPDATE 2:

Dank für die Eingabe aller. Das funktioniert:

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

Hat jemand eine Meinung darüber, ob es eine effizientere Möglichkeit gibt, dies zu tun? Oder ein Kopf darüber, wie dies auf verschiedenen Plattformen/Browsern oder unter anderen Umständen brechen könnte? Danke noch einmal.

Antwort

0

Diese Funktion akzeptiert ein Array und eine Blockgröße (in Ihrem Beispiel 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 
    } 
} 

wie folgt verwendet:

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

Dies ist eine flexible Lösung, bei der Sie die Blockgröße, wie Sie ändern können brauchen.

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

Wenn Sie immer ein Vielfaches von fünf haben, könnten Sie schwer, die Iteration über fünf Elemente codieren und eine äußere Schleife tun, die zu max/5 zählt und wechseln auf die Iteration rechts fest einprogrammiert.

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

Ich denke, die einfachste und klarste Lösung Nest zwei loos wäre:

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

Sie könnten jedoch auch nur mit einer Schleife und einem Loopcounter arbeiten. An den richtigen Stellen (4, 5, 14, 15, ...) würde sich die Richtung (Inkrement/Dekrement) ändern und der Zähler springt um eine Chunkgröße (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; 
} 

oder in einer for-Anweisung:

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

Sie etwas Kontext zu Ihrem Beitrag hinzufügen? Was ist die Idee? –

+0

Ich habe eine Schleife mit einem Zähler gemacht. An den richtigen Stellen (4, 5, 14, 15, ...) ändert sich die Richtung (Inkrement/Dekrement) und der Zähler springt um eine Chunksize (4 → 9, 5 → 10, 14 → 19, ...) – Bergi

+0

Ich habe eine Matrix von kleine Bilder in einem 15 x 15 Raster. Jedes Bild hat zwei Versionen (Ein und Aus). Ich möchte einen einfachen Bildwechsel auf jeder serpentinenweise machen (Zeile 1: von links nach rechts, Zeile 2: von rechts nach links, Zeile 3: von links nach rechts usw.). eine zusätzliche Falte wird sein, dass, nachdem die erste Reihe von Bildern "eingeschaltet" worden ist, sie in derselben Sequenz "ausgeschaltet" werden, während die Bilder in Zeile 2 "eingeschaltet" werden. Dies ist die Seite, wie sie jetzt steht: [hässlichesdigits.com] (http://www.uglydigits.com/index.html) Der Serpentineneffekt, den ich erreichen will, wird für die Reset-Funktion sein. –

Verwandte Themen