【问题标题】:execute javascsript for loop alternately forward and backward交替向前和向后执行 javascsript for 循环
【发布时间】:2012-10-14 08:50:59
【问题描述】:

以下更新

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

这个 sn-p 做了一个不同的动画。它从矩阵的右下角开始,“打开”底行的 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);
    }
}

是否有人对是否有更有效的方法有意见?或者在不同的平台/浏览器或不同的情况下,这可能会如何中断?再次感谢。

【问题讨论】:

    标签: javascript for-loop reverse


    【解决方案1】:
    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.

    【讨论】:

      【解决方案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

      如果您总是有 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);
        }
      }
      

      Fiddle

      【讨论】:

        【解决方案3】:

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

        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
        

        【讨论】:

        • 您可以在您的帖子中添加一些上下文吗?想法是什么?
        • 我用一个计数器做了一个循环。在正确的位置 (4, 5, 14, 15, ...),方向(增量/减量)发生变化,计数器跳跃一个块大小(4→9, 5→10, 14→19, ...)
        • 我有一个 15 x 15 网格中的小图像矩阵。每个图像都有两个版本(开启和关闭状态)。我想以蛇形方式对每个图像进行简单的图像交换(第 1 行:从左到右,第 2 行:从右到左,第 3 行:从左到右等)。另一个问题是,在第一行图像“打开”后,它们将按照相同的顺序“关闭”,而第 2 行中的图像正在“打开”。这是现在的网站:uglydigits.com 我试图实现的蛇形效果将用于重置功能。
        • 呃,如果它是一个动画,这意味着您可能必须异步执行它,而 for 循环对您没有帮助。但是,我获取 i 下一个值的公式可以帮助您
        • 此矩阵上的其他动画使用 for 循环。
        【解决方案4】:

        此函数接受一个数组和一个块大小(在您的示例中为 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]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-08-10
          • 2021-07-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多