5

更新如下

我正在尝试做的是以块的形式遍历数组,从块到块交替迭代的方向。使困惑?我也是。例如,如果我想遍历一个包含 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

4 回答 4

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

演示。

于 2012-10-14T09:17:25.220 回答
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);
}

小提琴

如果您总是有 5 的倍数,您可以在五个元素上硬编码迭代并执行一个外部循环,该循环计数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);
  }
}

小提琴

于 2012-10-14T09:05:35.293 回答
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, ...),方向(增量/减量)会改变,计数器会跳转一个块大小(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 语句中:

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
于 2012-10-14T14:50:48.027 回答
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]
于 2012-10-14T08:55:28.140 回答