Iterate unknown named object properties

Hi, im working on a function called howMuchOn(users) wich recieves an
object filled with objects as the following example shows:

let users = {
toni: {
age: 33,
online: true
},
emily: {
age: 25,
online: true
},
frank: {
age: 25,
online: false
},
henry: {
age: 24,
online: false
}
};

I need to get out of there just how mucho online:true there are.

Since i actually dont know the names that will come within the main object, i don’t know how to access the property “online” within object “name” within object “users”.

My function simplified looks like this (the question marks ‘???’ is where im stucked) :

function howMuchOn(users) {

var usersOn = 0;

for (var i = 0; i < users.length; i++) {
if ( usuarios.???.online === true){
usersOn += 1;
}
}
return usersOn;
}

I couldnt solve it with for…in loop eather, even tried Object.keys(users) to get an array of the names but couldnt use that array of strings to acces-
Is something like this posible? :

                                                  users[array[0]].online

I insist, its objects within an object, not an array of objects.

Thanks!

Yea, kinda 2d obj{}{} rather than 2d arr[][]. Got it!

Those are correct approaches in order to traverse the outer dimension of the 2d object container.

On the sketch below, I’m using a for...in loop in order to return all inner objects which are online as an array container:

/**
 * Traverse 2D Object Container (v1.0.0)
 * GoToLoop (2020-Aug-08)
 * Discourse.Processing.org/t/iterate-unknown-named-object-properties/23137/2
 */

'use strict';

var usersOn, users = {
  Tony: {
    age: 33,
    online: true
  },
  Emily: {
    age: 25,
    online: true
  },
  Frank: {
    age: 25,
    online: false
  },
  Henry: {
    age: 24,
    online: false
  }
};

usersOn = usersOnlineForIn(users);
console.info('for...in loop version:');
console.log(`There are ${usersOn.length} users online.`);
console.table(usersOn);

function usersOnlineForIn(users) {
  const usersOn = [];

  for (const key in users) {
    const user = users[key];
    user && user.online && usersOn.push(user);
  }

  return usersOn;
}

Given it’s vanilla JS code, you can just open a browser’s console and paste the whole code there.

Notice that within the loop block:

for (const key in users) {
  const user = users[key];
  user && user.online && usersOn.push(user);
}

I use the key iterator as the index for the users{}{} container:
const user = users[key];

We can also use a for...of loop for it:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of

Together w/ Object.keys():

For the same result as in for...in loop solution:

usersOn = usersOnlineObjKeys(users);
console.info('for...of + Object.keys() version:');
console.log(`There are ${usersOn.length} users online.`);
console.table(usersOn);

function usersOnlineObjKeys(users) {
  const usersOn = [];

  for (const key of Object.keys(users)) {
    const user = users[key];
    user && user.online && usersOn.push(user);
  }

  return usersOn;
}

Likewise, Object.entries() can get us there too:

usersOn = usersOnlineObjEntries(users);
console.info('for...of + Object.entries() version:');
console.log(`There are ${usersOn.length} users online.`);
console.table(usersOn);

function usersOnlineObjEntries(users) {
  const usersOn = [];

  for (const [ , user ] of Object.entries(users))
    user.online && usersOn.push(user);

  return usersOn;
}

However, if you don’t care to grab an array of online objects and just wanna count how many of them are online, the shortest code is via Object.values():

usersOn = howManyUsersOnlineObjValues(users);
console.info('for...of + Object.values() w/o array version:');
console.log(`There are ${usersOn} users online.`);

function howManyUsersOnlineObjValues(users) {
  var usersOn = 0;

  for (const { online } of Object.values(users))  online && ++usersOn;

  return usersOn;
}

Although Object.values() can also be used to return an array of online objects just like the Object.entries() approach:

usersOn = usersOnlineObjValues(users);
console.info('for...of + Object.values() version:');
console.log(`There are ${usersOn.length} users online.`);
console.table(usersOn);

function usersOnlineObjValues(users) {
  const usersOn = [];

  for (const user of Object.values(users))  user.online && usersOn.push(user);

  return usersOn;
}

Here is the 5 complete approaches in 1 sketch:

/**
 * Traverse 2D Object Container (v1.0.2)
 * GoToLoop (2020-Aug-08)
 * Discourse.Processing.org/t/iterate-unknown-named-object-properties/23137/2
 */

'use strict';

var usersOn, users = {
  Tony: {
    age: 33,
    online: true
  },
  Emily: {
    age: 25,
    online: true
  },
  Frank: {
    age: 25,
    online: false
  },
  Henry: {
    age: 24,
    online: false
  }
};

usersOn = usersOnlineForIn(users);
console.info('for...in loop version:');
console.log(`There are ${usersOn.length} users online.`);
console.table(usersOn);

usersOn = usersOnlineObjKeys(users);
console.info('for...of + Object.keys() version:');
console.log(`There are ${usersOn.length} users online.`);
console.table(usersOn);

usersOn = usersOnlineObjEntries(users);
console.info('for...of + Object.entries() version:');
console.log(`There are ${usersOn.length} users online.`);
console.table(usersOn);

usersOn = usersOnlineObjValues(users);
console.info('for...of + Object.values() version:');
console.log(`There are ${usersOn.length} users online.`);
console.table(usersOn);

usersOn = howManyUsersOnlineObjValues(users);
console.info('for...of + Object.values() w/o array version:');
console.log(`There are ${usersOn} users online.`);

function usersOnlineForIn(users) {
  const usersOn = [];

  for (const key in users) {
    const user = users[key];
    user && user.online && usersOn.push(user);
  }

  return usersOn;
}

function usersOnlineObjKeys(users) {
  const usersOn = [];

  for (const key of Object.keys(users)) {
    const user = users[key];
    user && user.online && usersOn.push(user);
  }

  return usersOn;
}

function usersOnlineObjEntries(users) {
  const usersOn = [];

  for (const [ , user ] of Object.entries(users))
    user.online && usersOn.push(user);

  return usersOn;
}

function usersOnlineObjValues(users) {
  const usersOn = [];

  for (const user of Object.values(users))  user.online && usersOn.push(user);

  return usersOn;
}

function howManyUsersOnlineObjValues(users) {
  var usersOn = 0;

  for (const { online } of Object.values(users))  online && ++usersOn;

  return usersOn;
}
2 Likes