1

Here is my code:

function iLoveThree (array) {
  var threes = [];
  var x;
  for (x in array) {
    if (x % 3 == 0) {
      threes.push(x)
    }
  }
  return threes
}

When I pass the array [1,2,3,4,5,6,7,8,9] I get the following:

Function returned 
["0","3","6"]
instead of 
[3,6,9]

My question is, where are these double quotes coming from?

1
  • 1
    Better don't use for...in to iterate arrays. Commented Dec 8, 2015 at 18:29

8 Answers 8

2

for...in is a bad way of iterating array indices. Better use filter:

[1,2,3,4,5,6,7,8,9].filter(function(x) {
  return x % 3 == 0;
}); // [3, 6, 9]
Sign up to request clarification or add additional context in comments.

2 Comments

Can you tell me why for...in is bad? Douglas Crockford also doesnt recommend it, I cant recall why though.
@RahulDesai See Why is using “for…in” with array iteration such a bad idea?. In this case for...in would be problematic because it does not guarantee any order, so the result would beimplementation dependent.
0

A for..in loop does not loop through the array elements, it loops through the indices of the array. So for:

var arr = ["a", "b", "c"]
for ( x in arr ) console.log( x );

You'll get the string keys of ["0", "1", "2"]

You can fix your code by replacing your loop with a native for loop:

for ( var x = 0; x < array.length; x++ ) {
    if (array[i] % 3 == 0)
        threes.push(array[i]);
}

2 Comments

This worked! Thank you. I had almost the same exact code earlier but I was using array[count] instead of a variable. Which is what @void said in his comment above.
Crockford has recommended array.forEach over the traditional for loop. Just an FYI.
0

So basically in x in array x is the index not the array value. Because anyway 0 is not in the array but your function is returning it as well. You should instead access the values using array[x]

There are various approaches, one of them is using .filter

function iLoveThree(array){
    return array.filter(function(x){
        return (x%3==0?1:0);
    });
}

Or

function iLoveThree (array) {
  var threes = [];
  var x;
  [].forEach.call(array, function(x){
    if (x % 3 == 0) {
      threes.push(x)
    }
  }
  return threes
}

Comments

0

You're using a for..in loop which gives you the keys in an object, or in this case and array. Keys are always strings. Instead, you want to use a standard for loop.

for (var i = 0; i < array.length; i++) {
  var x = array[i];
  if (x % 3 === 0) {
    threes.push(x);
  }
}

Or if you want to use a more functional approach, you could use Array.prototype.filter.

return array.filter(function(x) {
  return x % 3 === 0;
});

Comments

0

Not an answer to your question directly, but here's a nice way to pull every multiple of 3 from an array of numbers:

[1,2,3,4,5,6,7,8,9].filter(item => item % 3 === 0)

2 Comments

Note that arrow functions don't work in most browsers without transpiling.
@TbWill4321 The question didn't specify the JS version.
0

It seems that you are pushing in the indexes and not the actual values, go ahead and try the following:

function iLoveThree(array) {
    var threes = [];
    var x;
    for (x in array) {
        if (((x-2) % 3) == 0) {
            threes.push(array[x])
        }
    }
    return threes;
}

Another option, shorter, is:

function iLoveThree(arr) {
    var threes = [];
    for (var i = 2; i < arr.length; i = i + 3) {
        threes.push(arr[i]);
    };
    return threes;
}

if you are comfortable with callback/predicate based loops, you could make stuff even shorter by filtering the array, instead of creating a new one:

function iLoveThree(arr) {
    return arr.filter(function(x) {
        return (x % 3) == 0;
    });
}

Comments

0

Before you read the answer below, please read: Why is using “for…in” with array iteration such a bad idea? (Thanks to @Oriol for this link.)

Douglas Crockford has also discouraged the use of for..in. He recommends using array.forEach instead.

function iLoveThree (array) {
  var threes = [];

  array.forEach(function(item, i){  // use forEach, 'item' is the actual value and 'i' is the index
    if (item % 3 === 0) {
      threes.push(item); // you missed ; here
    }
  });

  return threes;  // you missed ; here
}

console.log(iLoveThree([1,2,3,4,5,6,7,8,9]));

Read up: Array.prototype.forEach() | MDN

Comments

-1

If you read the for...in documentation, you will realize that you are pushing to threes the indexes (also called keys) not the values, because the variable x represents the index, so the value should be accessed by array[x].

function iLoveThree (array) {
  var threes = [];

  for (var x in array) {
    if (array[x] % 3 == 0) {
      threes.push(array[x])
    }
  }
  return threes
}

There are several ways to achieve this, the best one is by using a filter, but that way was already explained by someone else, therefore I will use an exotic implementation using a reduce

[1, 2, 3, 4, 5, 6, 7, 8, 9].reduce(function(acc, e){return e % 3 == 0 ? acc.concat(e) : acc}, [])

Outputs 3, 6, 9

2 Comments

This still gives him an incorrect answer. He wants the values that are divisible by three, not the indices.
@TbWill4321 Solved, I was editing it, when you commented! But thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.