1

I am curious to know if you can place a for/in loop inside a for/in loop the way you can with a standard for loop. In the example below I am trying to list all of the properties of each game object but I am not getting the expected result. I have tried using dot notation and square brackets but neither seems to work. Is this not possible or am I overlooking something simple in the syntax?

var games = [{
    "name": "PCH Mystery Game",
    "maxScore": 50000,
    "levels": 4,
    "players": ["akshat", "joe", "dandan", "andrew"],
    "maps": {
      "1": 1,
      "2": 2,
      "3": 3,
      "4": 4
    }
  },
  {
    "name": "PCH Token Dash",
    "maxScore": 11500,
    "levels": 2,
    "players": ["andrew", "dandan", "matt", "mitchell", "hadi"],
    "maps": {
      "1": 1,
      "2": 2,
      "3": 3,
      "4": 4
    }
  },
  {
    "name": "PCH Balloon Drop",
    "maxScore": 500,
    "levels": 1,
    "players": [
      "akshat", "joe", "dandan", "dan", "mark", "nagesh", "jessie", "lou"
    ],
    "maps": {
      "1": 1,
      "2": 2,
      "3": 3,
      "4": 4
    }
  },
  {
    "name": "PCH Envelope Toss",
    "maxScore": 7000,
    "levels": 84,
    "players": ["akshat", "jessie", "joe", "andrew", "dandan"],
    "maps": {
      "1": 1,
      "2": 2,
      "3": 3,
      "4": 4
    }
  },
  {
    "name": "PCH Prize Patrol Race",
    "maxScore": 100000,
    "levels": 5,
    "players": [
      "akshat", "joe", "andrew", "dandan", "lou", "roberto", "jessie", "haim", "matt", "mitchell", "ian"
    ],
    "maps": {
      "1": 1,
      "2": 2,
      "3": 3,
      "4": 4
    }
  }
];

for (game in games) {
  document.write("game: " + games[game].name + "<br>");
  for (prop in game) {
    document.write("property name: " + prop + "<br>");
    document.write("property value: " + game[prop] + "<br>");
    document.write("property value: " + game.prop + "<br>");
  }
  document.write("<br>");
}
j08691
  • 204,283
  • 31
  • 260
  • 272
  • 2
    It has to be `for(prop in games[game])`, `game` is the **key** and not the **value**. – t.niese Apr 11 '18 at 16:14
  • It is always valuable to describe the logic for oneself in text first. – deEr. Apr 11 '18 at 16:16
  • 1
    https://stackoverflow.com/questions/500504/why-is-using-for-in-with-array-iteration-a-bad-idea – Xotic750 Apr 11 '18 at 16:16
  • The best part of JavaScript literal objects is being able to get the data without iterate too much. If you have control over the type of object you have you can get the data by the keys. As far as I know, it is possible to make a for in inside a for in. – desoares Apr 11 '18 at 16:18

2 Answers2

5

Fundamentally, yes, you can have nested for-in loops. That's not the problem in your code.

The variable in a for-in loop is the property name (or key), not the actual value. Separately, for-in isn't the correct way to loop through an array (although you can make it work if you try). See my answer here for a list of ways to loop through arrays.

In this case, you'd probably use forEach or (in modern environments) for-of or just a simple for loop for the outer loop through the array, and then a for-in loop (over the object properties)

games.forEach(function(game) {
    for (var prop in game) {
        console.log("property name: " + prop);
        console.log("property value: " + game[prop]);
    }
});

Live Example:

var games = [{
    "name": "PCH Mystery Game",
    "maxScore": 50000,
    "levels": 4,
    "players": ["akshat", "joe", "dandan", "andrew"],
    "maps": {
      "1": 1,
      "2": 2,
      "3": 3,
      "4": 4
    }
  },
  {
    "name": "PCH Token Dash",
    "maxScore": 11500,
    "levels": 2,
    "players": ["andrew", "dandan", "matt", "mitchell", "hadi"],
    "maps": {
      "1": 1,
      "2": 2,
      "3": 3,
      "4": 4
    }
  },
  {
    "name": "PCH Balloon Drop",
    "maxScore": 500,
    "levels": 1,
    "players": [
      "akshat", "joe", "dandan", "dan", "mark", "nagesh", "jessie", "lou"
    ],
    "maps": {
      "1": 1,
      "2": 2,
      "3": 3,
      "4": 4
    }
  },
  {
    "name": "PCH Envelope Toss",
    "maxScore": 7000,
    "levels": 84,
    "players": ["akshat", "jessie", "joe", "andrew", "dandan"],
    "maps": {
      "1": 1,
      "2": 2,
      "3": 3,
      "4": 4
    }
  },
  {
    "name": "PCH Prize Patrol Race",
    "maxScore": 100000,
    "levels": 5,
    "players": [
      "akshat", "joe", "andrew", "dandan", "lou", "roberto", "jessie", "haim", "matt", "mitchell", "ian"
    ],
    "maps": {
      "1": 1,
      "2": 2,
      "3": 3,
      "4": 4
    }
  }
];

games.forEach(function(game) {
    for (var prop in game) {
        console.log("property name: " + prop);
        console.log("property value: " + game[prop]);
    }
});

But you have lots of options, particularly in modern environments. For instance:

for (const game of games) {
    for (const [prop, value] of Object.entries(game)) {
        console.log(`${prop} is ${value}`);
    }
}

...uses for-of, destructuring, and Object.entries.

Live Example:

var games = [{
    "name": "PCH Mystery Game",
    "maxScore": 50000,
    "levels": 4,
    "players": ["akshat", "joe", "dandan", "andrew"],
    "maps": {
      "1": 1,
      "2": 2,
      "3": 3,
      "4": 4
    }
  },
  {
    "name": "PCH Token Dash",
    "maxScore": 11500,
    "levels": 2,
    "players": ["andrew", "dandan", "matt", "mitchell", "hadi"],
    "maps": {
      "1": 1,
      "2": 2,
      "3": 3,
      "4": 4
    }
  },
  {
    "name": "PCH Balloon Drop",
    "maxScore": 500,
    "levels": 1,
    "players": [
      "akshat", "joe", "dandan", "dan", "mark", "nagesh", "jessie", "lou"
    ],
    "maps": {
      "1": 1,
      "2": 2,
      "3": 3,
      "4": 4
    }
  },
  {
    "name": "PCH Envelope Toss",
    "maxScore": 7000,
    "levels": 84,
    "players": ["akshat", "jessie", "joe", "andrew", "dandan"],
    "maps": {
      "1": 1,
      "2": 2,
      "3": 3,
      "4": 4
    }
  },
  {
    "name": "PCH Prize Patrol Race",
    "maxScore": 100000,
    "levels": 5,
    "players": [
      "akshat", "joe", "andrew", "dandan", "lou", "roberto", "jessie", "haim", "matt", "mitchell", "ian"
    ],
    "maps": {
      "1": 1,
      "2": 2,
      "3": 3,
      "4": 4
    }
  }
];

for (const game of games) {
    for (const [prop, value] of Object.entries(game)) {
        console.log(`${prop} is ${value}`);
    }
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

Clearer than for(prop in games[game]) is

for (i in games) {
  var game = games[i];
  document.write("game: " + game.name + "<br>");
  for (prop in game) {
    document.write("property name: " + prop + "<br>");
    document.write("property value: " + game[prop] + "<br>");
  }
  document.write("<br>");
}

Note that for...in is not typically used in arrays as much, since arrays are typically expected to have an order and for...in won't necessarily respect order. It's a few more keystrokes, but there's nothing wrong with for (i = 0; i < games.length; i++) and then continuing the same way.

Sam Fen
  • 5,074
  • 5
  • 30
  • 56