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 要素のチャンクでトラバースしたいので、スケーラブルなものを探していますが、それはある時点で変更される可能性があります。これまでのところ、実際に機能するとわかっている唯一の方法は、反復順序を 2 番目の配列に配線し、それを通常の方法で反復して元の配列のインデックスを取得することです。しかし、それはひどいです。どんな助けでも大歓迎です。

@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 行上に移動し、その行のタイルをオンにして、前の行のタイルをオフにします。一番上の行がオンになってからオフになるまで、というように続きます。私が新しい関数で達成しようとしているトップダウンの曲がりくねった効果からそれほど離れていません。各行の逆順は、私を困惑させた主なものでした. そうは言っても、上記のコードの最適化に関する提案も大歓迎です。

更新 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 の倍数である場合は、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

最も簡単で明確な解決策は、2つのトイレをネストすることだと思います。

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

ただし、ループとループカウンターを1つだけ使用することもできます。適切な場所(4、5、14、15、…)では、方向(インクリメント/デクリメント)が変更され、カウンターは1チャンクサイズ(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;
}

または、1つのステートメントで:

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 に答える