2012-10-14 15 views
5

AGGIORNAMENTO SOTTOeseguire javascsript ciclo alternativamente avanti e indietro

Quello che sto cercando di fare è un'iterazione in un array in pezzi, alternando la direzione di iterazione da un pezzo all'altro. Confuso? Lo sono anch'io. Per esempio, se voglio eseguire il ciclo su un array con 25 elementi, ma voglio farlo in questo ordine: 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, quale sarebbe il modo più efficace per farlo? Sto cercando qualcosa di scalabile perché l'array con cui sto lavorando ora è in realtà 225 elementi e voglio attraversarlo in 15 elementi, ma a un certo punto potrebbe cambiare. Finora, l'unico metodo che ho capito che funziona davvero è quello di cablare l'ordine di iterazione in un secondo array e poi scorrere attraverso quello nel modo normale per ottenere gli indici per l'array originale. Ma questo fa schifo. Qualsiasi aiuto sarebbe molto apprezzato.

@Bergi ha richiesto un codice di esempio. Per favore non picchiarmi troppo. Sono ancora un 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); 
    } 
} 

Questo snippet esegue un'animazione diversa. Inizia nell'angolo in basso a destra della matrice e "attiva" le 15 tessere nella riga inferiore. poi si sposta su una fila, accende le tessere in quella fila e spegne le tessere nella riga precedente. E così via fino a quando la fila in alto non viene accesa e poi spenta. non molto lontano dall'effetto serpentino dall'alto verso il basso che sto cercando di ottenere nella nuova funzione. L'ordine di inversione su ogni fila era la cosa principale che mi bloccava. Detto questo, qualsiasi suggerimento sull'ottimizzazione del codice sopra sarebbe anche molto apprezzato.

UPDATE 1:

Per me, questo sembra come dovrebbe funzionare, ma non è così. Qualcuno può individuare il problema?

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:

Grazie per l'input di tutti. Questo funziona:

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

Qualcuno ha un parere in merito, se c'è un modo più efficiente di fare questo? O un testa a testa su come questo potrebbe rompersi su diverse piattaforme/browser o in circostanze diverse? Grazie ancora.

risposta

0

Questa funzione accetta un array e un blocksize (nel tuo esempio, 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 
    } 
} 

usati in questo modo:

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

Si tratta di una soluzione flessibile in cui è possibile modificare la dimensione del blocco, come si bisogno di essa.

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

Se si ha sempre un multiplo di cinque, si potrebbe difficile codificare l'iterazione su cinque elementi e fare un ciclo esterno che conta per max/5 e passare a destra hardcoded iterazione.

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

Credo che la soluzione più semplice e più chiara sarebbe quella di nido due Loos:

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

Tuttavia, si potrebbe anche andare con un solo loop e loopcounter. Nei punti giusti (4, 5, 14, 15, ...) la direzione (incremento/decremento) cambierà e il contatore salterà un chunksize (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; 
} 

o, in uno per-dichiarazione:

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

si può aggiungere un po 'di contesto al tuo post? Qual è l'idea? –

+0

Ho fatto un ciclo con un contatore. Nei punti giusti (4, 5, 14, 15, ...) la direzione (incremento/decremento) cambia e il contatore salta un chunksize (4 → 9, 5 → 10, 14 → 19, ...) – Bergi

+0

Ho una matrice di piccole immagini in una griglia 15 x 15. Ogni immagine ha due versioni (uno acceso e uno spento). Voglio fare un semplice scambio di immagini su ciascuna in modo serpentino (riga 1: da sinistra a destra, riga 2: da destra a sinistra, riga 3: da sinistra a destra, ecc.). un'increspatura aggiunta sarà che dopo che la prima fila di immagini viene "accesa", verranno "spente" nella stessa sequenza mentre le immagini nella riga 2 verranno "accese". questo è il sito così com'è ora: [uglydigits.com] (http://www.uglydigits.com/index.html) L'effetto serpentino che sto cercando di ottenere sarà per la funzione di reset. –

Problemi correlati