user1576121
user1576121

Reputation: 115

Nested for...in statements in JavaScript

I'm trying to learn JavaScript in Codecademy and one of the things mentioned briefly are "for in" loops. I've used them in a few of the exercises, but in this case I can't get it to work. I could do it with for (i = blah; etc), but I'd like to know what's wrong with this and if there's a way to fix it:

//Your three dimensional array from the last exercise probably
//looked something like this:
var hands = [];
hands[0] = [ [3,"H"], ["A","S"], [1,"D"], ["J","H"], ["Q","D"] ];
hands[1] = [ [9,"C"], [6,"C"], ["K","H"], [3,"C"], ["K","H"] ];

//Loop over every dimension in the array, logging out the suit and rank
//of each card in both hands
//1. loop over each hand
for (var hand in hands) {
//2. loop over each card array in each hand
    for (var card in hand) {
        //3. loop over each rank/suit array for each card in each hand
        for (var prop in card) {
            //4. log the value of the rank/suit array item
            console.log(card[prop]);
        }
    }
}

The output is 0 0 0, instead of the number and suit. I tried placing console.log() after the first and second loop and I noticed it works correctly in the first, but not in the second one.

Upvotes: 3

Views: 7806

Answers (2)

user1106925
user1106925

Reputation:

Momentarily ignoring the for-in issue, your inner loops should look like this...

for (var hand in hands) {
    for (var card in hands[hand]) {
        for (var prop in hands[hand][card]) {
            console.log(hands[hand][card][prop]);
        }
    }
}

Notice that each inner loop needs to explicitly reference the current value of its outer loop. You are iterating over the keys (the variable before in) instead.


To deal with Arrays properly, you should almost always use a for loop instead of for-in.

for (var i = 0; i < hands.length; i++) {
    for (var j = 0; j < hands[i].length; j++) {
        for (var k = 0; k < hands[i][j].length; k++) {
            console.log(hands[i][j][k]);
        }
    }
}

There are a few reasons for this, which you can find on StackOverflow.


To add clarity to the code, you can cache the current item in a variable...

for (var i = 0; i < hands.length; i++) {
    var hand = hands[i]
    for (var j = 0; j < hand.length; j++) {
        var cards = hand[j];
        for (var k = 0; k < cards.length; k++) {
            console.log(cards[k]);
        }
    }
}

Upvotes: 11

nickf
nickf

Reputation: 546045

You shouldn't use for..in loops on arrays, since it doesn't just loop over the indexed members of the array, but all properties of the object. Instead, you can use a 'traditional' for loop, or the ECMAScript 5 .forEach

var hand, card, prop, h, c, p;

for (h = 0; h < hands.length; ++h) {
    hand = hands[h];
    for (c = 0; c < hand.length; ++c) {
        card = hand[c];
        for (p = 0; p < card.length; ++p) {
            prop = card[p];
            console.log(prop);
        }
    }
}

There are shorter ways to do the above, but that's a basic and readable method.

Upvotes: 2

Related Questions