So a for…in statement iterates through the key/value pairs in an object. So the reason the nested loop works is because you have nested objects inside of an object.
for (let user in users){
The first loop is looping through each key in users. The first loop it will grab Alan, then it will grab Jeff, then Sarah, and finally Ryan.
The nested loop is accessing the key value pairs inside each person object. So when the first loop is iterating through Alan, the nested loop will first grab age, then online. Then the first loop goes to Jeff and the nested loop goes back to age, then online, and so on until it makes it through each set of key value pairs for each person in the object “users”.
Does that make sense?
This would be useful if you didn’t know the key value pairs in an object. Otherwise you could do one loop and access the nested key value pairs with something like:
for (let user in users){
if (user.age >= 18) //do something
}
The job of countOnline is to return how many users have the property online set to true. If you look at the users object, you can see it is 2. Your job is to create the countOnline.
You need a counter to store how many users are online.
You need to loop through each user and check if the user is online, if he is, you increment the counter, if not, you ignore.
You need to return the counter.
Hope this helps, give it a try, if you can’t get it to work, please post your code.
function countOnline(obj) {
// change code below this line
let i = 0;
for(let user in obj){
user.online ? i += 1: null;
};
return i;
// change code above this line
}
I have tried this and I am just getting 0. I know this is probably obvious, but something is just not clicking for me so I am genuinely stuck.
I also tried
function countOnline(obj) {
// change code below this line
let i = 0;
for(let user in obj){
for(let line in user){
line == true ? i++ : null;
}
}
return i;
// change code above this line
}
With the double == it returns 4, with the === it returns 0.
I am really lost. I get the concept. I get what we are trying to do. But I just don’t get it.
Your explanation was really impressive because I wasn’t sure it could be explained to me without just giving me the answer. But your repl really helped me just think things through more logically to realize what assumptions I was making.
Is it safe to say that the issue I was having was because I was not being specific enough with the second for…in loop? I was assuming that the js engine knew to loop through the nested object when in fact it didn’t?
It’s not a matter of specificity in the second for loop. The second loop was not referencing what you thought it was.
let’s look at your code:
function countOnline(obj) {
// change code below this line
let i = 0;
for(let user in obj){
for(let line in user){
line == true ? i++ : null;
}
}
return i;
// change code above this line
}
In the first for loop you are grabbing the key, user from obj. Then we take that userkey and look at each line. This is the mistake. In for(let line in user) you thought user was the user object. It was actually just the key
When you thought you were passing in:
Alan: {
age: 27,
online: false
}
into your second for loop, you were actually passing in:
Alan
So what this line,for(let line in user) is doing is iterating through that string, Alan. And when you console.log(line) you will see a number, this is the string’s index. If you then reference the value of that index, you get back the character. For ex:
for (let line in user) {
console.log(user[line])
}
// the loop iterates 4 times (because Alan is 4 characters long and the output would be:
// 'A'
// 'l'
// 'a'
// 'n'
What we are interested in the second for in loop is the value not the key. So in order to look at the value of the key, we need to reference the parent object with bracket notation obj[user]. The value in this case is an object, a user object.
(You could also use dot notation, but one step at a time. There are constraints to dot notation vs. bracket notation I could go into if needed)
function countOnline(obj) {
// change code below this line
let i = 0;
for(let user in obj){
user.online ? i += 1: null;
};
return i;
// change code above this line
}
What you missed is that line in the challenge explanation:
“Sometimes you may need to iterate through all the keys within an object.”
As @psbyron3 explained, when you use user.online you’re actually calling online on a key, which are just strings: Alan, Jeff, Sarah and Ryan. What you must do is to grab the value that key has, for example: obj[user].online.
After reading thru this a few times I think I get it but I kept getting 8 instead of 2 until I used a break and now it works and I pass the tests… Is this correct?
function countOnline(obj) {
// change code below this line
let onlineCount = 0;
for (let user in users) {
console.log(user)
console.log(users[user].online)
for (let data in user) {
if (users[user].online === true) {
onlineCount += 1;
break;
}
}
}
return onlineCount; // change code above this line
};
You don’t need the second loop at all, you are already in the individual user so you just access the object property like users[user].online. Don’t loop over objects if you don’t need to. Get rid of the inner loop and the break, you only need if (users[user].online) onlineCount++