1

In NodeJS, I created the following two scripts, both of them was intended to remove even numbers from an array.

This is my 1st script:

#!/usr/bin/nodejs
var myarr = [2,3,5,1,6,2,28,5,7,90,3];
console.log(myarr);
for(var i in myarr){
        if(myarr[i] % 2 == 0){
                myarr.splice(i,1);
                --i;
        }
}
console.log(myarr);

Output for the first script was following:

[ 2, 3, 5, 1, 6, 2, 28, 5, 7, 90, 3 ]
[ 3, 5, 1, 2, 5, 7, 3 ]

In 2nd script, I changed for..in loop to for(;;) loop as follows:

#!/usr/bin/nodejs
var myarr = [2,3,5,1,6,2,28,5,7,90,3];
console.log(myarr);
for(var i=0;i<myarr.length;i++){
        if(myarr[i] % 2 == 0){
                myarr.splice(i,1);
                --i;
        }
}
console.log(myarr);

I got following output for the 2nd script:

[ 2, 3, 5, 1, 6, 2, 28, 5, 7, 90, 3 ]
[ 3, 5, 1, 5, 7, 3 ]

Although my intention was the same, two for loops gave me different outputs. I figured out that, in my first script, if there are two adjacent even numbers exist in the original array, if condition seems to be applied for the first even number only where the second even number is skipped. I would really appreciate if anybody can explain this difference clearly.

James Donnelly
  • 126,410
  • 34
  • 208
  • 218
Deepal
  • 1,729
  • 5
  • 24
  • 34
  • 2
    Don't use `for...in` to iterate over an array (or a collection in general). – MaxArt Dec 12 '14 at 10:45
  • 3
    iterating and removing at the same time is not a good idea. – artur grzesiak Dec 12 '14 at 10:45
  • And to better get an idea what is happening, put this `console.log('i = ' , i, ' myarr = ', myarr);` after this `for(var i in myarr){` . – Yogesh Khatri Dec 12 '14 at 10:53
  • http://es5.github.io/#x12.6.4: "*A property name must not be visited more than once in any enumeration.*". Your `--i` in the `for in`-loop is futile (you could use a `while` instead of the `if` however). – Bergi Dec 12 '14 at 11:29

1 Answers1

3

What you're doing is wrong. You're removing keys from the array whilst looping through the same array. Your for...in loop will only ever perform 7 iterations, as 4 of your keys are spliced from the array whilst the array is still being iterated through, whereas your for(;;) loop will always perform all 11 iterations as this is defined at the beginning (myarr.length).

You should define a second array to use for your results instead:

for...in

var myarr = [2,3,5,1,6,2,28,5,7,90,3],
    resultarr = [];
console.log(myarr);
for(var i in myarr){
    if(myarr[i] % 2 != 0){
        resultarr.push(myarr[i])
    }
}
console.log(resultarr);
-> [3, 5, 1, 5, 7, 3]

for(;;)

var myarr = [2,3,5,1,6,2,28,5,7,90,3],
    resultarr = [];
console.log(myarr);
for(var i=0;i<myarr.length;i++){
    if(myarr[i] % 2 != 0){
        resultarr.push(myarr[i]);
    }
}
console.log(resultarr);
-> [3, 5, 1, 5, 7, 3]

As an ending note, you shouldn't use the for...in loop for iterating through arrays anyway. This answer details why this is a bad idea.

Community
  • 1
  • 1
James Donnelly
  • 126,410
  • 34
  • 208
  • 218
  • Thank you very much for your explaination. I knew I could use a second array to push odd numbers. But I wanted to do it without using any additional arrays. – Deepal Dec 12 '14 at 10:56