2012-10-14 10 views
5

AKTUALIZACJA PONIŻEJwykonać javascsript do pętli na przemian do przodu i do tyłu

Co usiłuję zrobić jest iterację tablicy w kawałkach, na przemian kierunek iteracji od kawałka do kawałka. Zmieszany? Ja też. Na przykład, jeśli chcę zapętlić się przez tablicę z 25 elementami, ale chcę to zrobić w tej kolejności: 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, jaki byłby najskuteczniejszy sposób robienia tego? Szukam czegoś skalowalnego, ponieważ macierz, z którą teraz pracuję, to w rzeczywistości 225 elementów i chcę ją przemierzyć w 15 elementach, ale to może się w pewnym momencie zmienić. Do tej pory jedyną metodą, którą odkryłem, która faktycznie działa, jest sztywne połączenie kolejności iteracji w drugą macierz, a następnie iterowanie w normalny sposób, aby uzyskać indeksy dla oryginalnej tablicy. Ale to jest do bani. Każda pomoc będzie bardzo ceniona.

@Bergi poprosił o kod przykładowy. Proszę, nie bij mnie za bardzo. Nadal jestem noobem:

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

Ten fragment kodu przedstawia inną animację. Zaczyna się w prawym dolnym rogu matrycy i "włącza" 15 płytek w dolnym rzędzie. następnie przesuwa się w górę rzędu, włącza płytki w tym rzędzie i wyłącza płytki w poprzednim rzędzie. I tak dalej, aż górny rząd zostanie włączony, a następnie wyłączony. niezbyt daleko od efektu góry w dół serpentyn, który staram się osiągnąć w nowej funkcji. Kolejność odwrotu w każdym rzędzie była dla mnie najważniejsza. W związku z tym wszelkie sugestie dotyczące optymalizacji powyższego kodu również będą mile widziane.

UPDATE 1:

Dla mnie to wydaje się, że powinna działać, ale tak nie jest. Czy ktoś może zauważyć problem?

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:

Dzięki za wkład każdego z nas. Działa to:

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

Czy ktoś ma opinię na temat, czy jest bardziej efektywny sposób to zrobić? Albo dowiedzieć się, jak to może wpłynąć na różne platformy/przeglądarki lub w innych okolicznościach? Dzięki jeszcze raz.

Odpowiedz

0

Funkcja ta przyjmuje tablicę i rozmiar bloku (w przykładzie, 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 
    } 
} 

Używane tak:

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

Jest to elastyczne rozwiązanie, w którym można zmienić rozmiar bloku jak ty potrzebuję tego.

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

Jeśli masz zawsze wielokrotność pięciu, można kodować iteracji ciężko nad pięcioma żywiołami i zrobić pętlę zewnętrzną, która liczy na max/5 i przełączyć się na prawej sztywno iteracji.

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

Chyba najprostszym i najczystszych rozwiązaniem byłoby gnieździe dwa 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); 

Można jednak użyć tylko jednej pętli i licznika pętli. W odpowiednich miejscach (4, 5, 14, 15, ...) zmieni się kierunek (inkrementacja/dekrementacja), a licznik przeskoczy o jeden rozmiar (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; 
} 

lub w jednym dla-stwierdzeniem:

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

można dodać kontekst do postu? Jaki jest pomysł? –

+0

Zrobiłem pętlę z jednym kontuarem. W odpowiednich miejscach (4, 5, 14, 15, ...) zmienia się kierunek (inkrementacja/dekrementacja), a licznik przeskakuje jeden fragment (4 → 9, 5 → 10, 14 → 19, ...). – Bergi

+0

Mam matrycę małe obrazy w siatce 15 x 15. Każdy obraz ma dwie wersje (stan włączony i wyłączony). Chcę zrobić zwykłą zamianę obrazów na serpentynę (wiersz 1: od lewej do prawej, wiersz 2: od prawej do lewej, wiersz 3: od lewej do prawej itd.). Dodatkowym zmarszczeniem będzie to, że po tym, jak pierwszy rząd obrazów zostanie "włączony", zostaną one "wyłączone" w tej samej sekwencji, podczas gdy obrazy w rzędzie 2 zostaną "włączone". to jest strona w obecnej postaci: [uglydigits.com] (http://www.uglydigits.com/index.html) Efekt serpentynowy, który próbuję osiągnąć, będzie dotyczył funkcji resetowania. –

Powiązane problemy