0

I have objects (people) inside an array (group) inside an object (data) like so:

const data = {
  g1 : [
    {"name" : "Jack", "age" : 32},
    {"name" : "Jill", "age" : 44}    
  ],
  g2 : [
    {"email" : "jane@example.com", "city" : "Berlin", "age" : 14},
    {"email" : "brad@example.com", "city" : "Stockholm", "age" : 22}
  ]
}

Say I want to console.log all age property values, I try:

for (const group in data) {
  for (const person of group) {
    console.log(person.age)
  }
}

This does not work. It seems for (const group in data) is only looping over the names of it's children. I assume I should not use for...in in this case, but what can I use? Or is it somehow possible to use for...in?

The reason I'm confused is because in for example PHP I could do:

<?php

$data = [
    "g1" => [
        [ "name" => "Jack", "age" => 32 ],
        [ "name" => "Jill", "age" => 44 ]
    ],
    "g2" => [
        [ "email" => "jane@example.com", "city" => "Berlin", "age" => 14 ],
        [ "email" => "brad@example.com", "city" => "Stockholm", "age" => 22 ]
    ]
];


foreach ( $data as $group ) {
    foreach ( $group as $person ) {
        echo $person[ 'age' ];
    }
}

and in would work.

Dirk J. Faber
  • 4,360
  • 5
  • 20
  • 58
  • 1
    You'd need `const person of data[group]` since `group` is the key. Another way is to use `Object.values(data).forEach(group => group.forEach(person => console.log(person.age)));` –  Dec 27 '19 at 17:08
  • Since you found out that the outer loop gets you `"g1"` and `"g2"`, this is basically a dupe of https://stackoverflow.com/questions/4244896/dynamically-access-object-property-using-variable –  Dec 27 '19 at 17:12

8 Answers8

3

One easier way is:

const data = {
  g1: [{
      "name": "Jack",
      "age": 32
    },
    {
      "name": "Jill",
      "age": 44
    }
  ],
  g2: [{
      "email": "jane@example.com",
      "city": "Berlin",
      "age": 14
    },
    {
      "email": "brad@example.com",
      "city": "Stockholm",
      "age": 22
    }
  ]
};

console.log(Object.values(data).map(p => p.map(o => o.age)).flat());
Yousername
  • 1,012
  • 5
  • 15
2

The for...in construct will provide you only with the keys of an object, not its values. In your outer loop:

for (const group in data) { ... }

... the variable group will be set to g1, then g2, not to the value of the group. To get the value (i.e., the person), you need to index the group:

for (const group in data) {
  for (const person of data[group]) {
    console.log(person.age)
  }
}
Alexander van Oostenrijk
  • 4,644
  • 3
  • 23
  • 37
1

There is a much easier way:

const data = {
  g1 : [
    {"name" : "Jack", "age" : 32},
    {"name" : "Jill", "age" : 44}    
  ],
  g2 : [
    {"email" : "jane@example.com", "city" : "Berlin", "age" : 14},
    {"email" : "brad@example.com", "city" : "Stockholm", "age" : 22}
  ]
}

Object.values(data).forEach(group=>group.forEach(person=>console.log(person.age)));

Here's another version:

const data = {
  g1 : [
    {"name" : "Jack", "age" : 32},
    {"name" : "Jill", "age" : 44}    
  ],
  g2 : [
    {"email" : "jane@example.com", "city" : "Berlin", "age" : 14},
    {"email" : "brad@example.com", "city" : "Stockholm", "age" : 22}
  ]
}

Object.entries(data).forEach(
  group=>group[1].forEach(
    person=>console.log(
        group[0], 
        person.name ? person.name : person.email, 
        person.age)
  )
);

Object.entries return the list of properties and values in an object in an array, i.e., [[prop, val], [prop, val], ...].

So if you use forEach in it, the 0 index will be prop name, and 1 index will be value. This explains the

    Object.entries(data).forEach(
      group=>group[1]

part. So now we have the group name, and the val which is an array of persons. Then you can just iterate it with another forEach and get age property:

   [...]group[1].forEach(
           person=>console.log(person.age));

I just elaborated it a bit to get more relevant information with

   [...]group[1].forEach(
       person=>console.log(
           group[0], 
           person.name ? person.name : person.email, 
           person.age)
       )
    ) [...]
Nelson Teixeira
  • 6,297
  • 5
  • 36
  • 73
  • @ArthurVaïsse Better now ? – Nelson Teixeira Dec 27 '19 at 17:24
  • 1
    Yep! It is better this way. I still consider the for loop as way more explicit and simpler to tackle this simple problem though. I would only prefer functional style if I were needing some mapping or filtering on the dataset. – Arthur Vaïsse Dec 27 '19 at 18:07
1

many answers here advise using different methods but do not address your issue, or what was missing in your implementation for the ages to be printed.

what you were missing is accessing the values of the group, which you iterate.

try this:

for (const group in data) {
  for (const person of data[group]) {
    console.log(person.age)
  }
}

which will output

32
44
14
22
Mr.
  • 9,429
  • 13
  • 58
  • 82
1

Let's try something clean and simple.

const data = {
  g1 : [
    {"name" : "Jack", "age" : 32},
    {"name" : "Jill", "age" : 44}    
  ],
  g2 : [
    {"email" : "jane@example.com", "city" : "Berlin", "age" : 14},
    {"email" : "brad@example.com", "city" : "Stockholm", "age" : 22}
  ]
}

consoleAllAges = obj => {
    for (i in obj) {
        const group = obj[i];
        group.forEach(person => {
            console.log(person.age);
        });
    }
}
0

group is an An Array and not An Object. Instead try this

    for (const group in data) {
  for (const person of data[group]) {
    console.log(person.age)
  }
}  ​
Saurav
  • 197
  • 8
0

You can use Object.values(data) to return the two arrays g1 and g2 in one array. Then you want to use flat() for this array which will give you a single array with all the people inside. Finally you want to call map() to iterate over this array. Since p.age is implicitly returned to map() it will return an array with all the returned values.

console.log(Object.values(data).flat().map(p=>p.age));
fubar
  • 383
  • 2
  • 11
0

Strings correction

  g1 : [
    {"name" : "Jack", "age" : 32},
    {"name" : "Jill", "age" : 44}    
  ],
 g2 : [
    {"email" : "jane@example.com", "city" : "Berlin", "age" : 14},
    {"email" : "brad@example.com", "city" : "Stockholm", "age" : 22}
  ]
}

change string inside
Cak Sup
  • 17
  • 9