执行javascript for循环或前进和后退

时间:2012-10-14 08:51:00

标签: javascript for-loop reverse

更新

我要做的是以块的形式迭代数组,将块的迭代方向交替到块。困惑?我也是。例如,如果我想通过一个包含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);
    }
}

有没有人对是否有更有效的方法有意见?或者了解这可能会在不同平台/浏览器上或在不同情况下破坏?再次感谢。

4 个答案:

答案 0 :(得分: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 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

答案 2 :(得分:1)

我想最简单,最清晰的解决方案是嵌套两个厕所:

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

但是,你也可以只使用一个循环和循环计数器。在正确的位置(4,5,14,15,...)方向(增量/减量)将改变,计数器跳跃一个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;
}

或者,在一个for-statement中:

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

答案 3 :(得分: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]