admin管理员组文章数量:1430346
UPDATED BELOW
What I'm trying to do is iterate through an array in chunks, alternating the direction of iteration from chunk to chunk. Confused? So am I. For example, if I want to loop thru an array with 25 elements, but I want to do it in this order: 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, what would be the most efficient way of doing this? I'm looking for something scalable because the array I'm working with now is actually 225 elements and I want to traverse it in 15 element chunks, but that may change at some point. So far, the only method I've figured out that actually works is to hard-wire the iteration order into a second array and then iterate through that in the normal way to get the indices for the original array. But that sucks. Any help would be greatly appreciated.
@Bergi asked for some sample code. Please don't beat me up too much. I'm still a noob:
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);
}
}
This snippet does a different animation. It starts at the lower right corner of the matrix and "turns on" the 15 tiles in the bottom row. then it moves up a row, turns on the tiles in that row and turns off the tiles in the previous row. And so forth until the top row is turned on then off. not very far off really from the top-down serpentine effect I'm trying to achieve in the new function. The reversing order on each row was the main thing stumping me. That being said, any suggestions about optimizing the above code would also be greatly appreciated.
UPDATE 1:
To me, this seems like it should work, but it doesn't. Can anyone spot the 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:
Thanks for everyone's input. This works:
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);
}
}
Does anyone have an opinion on if there is a more efficient way of doing this? Or a heads up on how this might break on different platforms/browsers or under different circumstances? Thanks again.
UPDATED BELOW
What I'm trying to do is iterate through an array in chunks, alternating the direction of iteration from chunk to chunk. Confused? So am I. For example, if I want to loop thru an array with 25 elements, but I want to do it in this order: 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, what would be the most efficient way of doing this? I'm looking for something scalable because the array I'm working with now is actually 225 elements and I want to traverse it in 15 element chunks, but that may change at some point. So far, the only method I've figured out that actually works is to hard-wire the iteration order into a second array and then iterate through that in the normal way to get the indices for the original array. But that sucks. Any help would be greatly appreciated.
@Bergi asked for some sample code. Please don't beat me up too much. I'm still a noob:
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);
}
}
This snippet does a different animation. It starts at the lower right corner of the matrix and "turns on" the 15 tiles in the bottom row. then it moves up a row, turns on the tiles in that row and turns off the tiles in the previous row. And so forth until the top row is turned on then off. not very far off really from the top-down serpentine effect I'm trying to achieve in the new function. The reversing order on each row was the main thing stumping me. That being said, any suggestions about optimizing the above code would also be greatly appreciated.
UPDATE 1:
To me, this seems like it should work, but it doesn't. Can anyone spot the 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:
Thanks for everyone's input. This works:
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);
}
}
Does anyone have an opinion on if there is a more efficient way of doing this? Or a heads up on how this might break on different platforms/browsers or under different circumstances? Thanks again.
Share Improve this question edited Oct 15, 2012 at 18:21 Stiff Mittens asked Oct 14, 2012 at 8:50 Stiff MittensStiff Mittens 715 bronze badges 04 Answers
Reset to default 4var 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.
This is a flexible solution where you can change the blocksize as you need it.
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
If you have always a multiple of five, you could hard code the iteration over five elements and do an outer loop which counts to max/5
and switch to the right hardcoded iteration.
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
I guess the simplest and clearest solution would be to nest two 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);
However, you could also go with only one loop and loopcounter. In the right spots (4, 5, 14, 15, …) the direction (increment/decrement) would change and the counter jumps one 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;
}
or, in one 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
This function accepts an array and a blocksize (in your example, 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
}
}
Used like this:
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]
本文标签: javascriptexecute javascsript for loop alternately forward and backwardStack Overflow
版权声明:本文标题:javascript - execute javascsript for loop alternately forward and backward - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745450593a2658863.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论