I have a object with all my users, like so: var users = {user1:{}, user2:{}}
, And every user has a isPlaying property. How do I get all users that have isPlaying false?
You should use Object.keys
, Array.prototype.filter
and Array.prototype.map
:
// This will turn users object properties into a string array
// of user names
var userNames = Object.keys(users);
// #1 You need to filter which users aren't playing. So, you
// filter accessing users object by user name and you check that
// user.isPlaying is false
//
// #2 Using Array.prototype.map, you turn user names into user objects
// by projecting each user name into the user object!
var usersNotPlaying = userNames.filter(function(userName) {
return !users[userName].isPlaying;
}).map(function(userName) {
return users[userName];
});
If it would be done using ECMA-Script 6, you could do using arrow functions:
// Compact and nicer!
var usersNotPlaying = Object.keys(users)
.filter(userName => users[userName].isPlaying)
.map(userName => users[userName]);
Array.prototype.reduce
As @RobG has pointed out, you can also use Array.prototype.reduce
.
While I don't want to overlap his new and own answer, I believe that reduce
approach is more practical if it returns an array of user objects not playing .
Basically, if you return an object instead of an array, the issue is that another caller (ie a function which calls the one doing the so-called reduce
) may need to call reduce
again to perform a new operation, while an array is already prepared to fluently call other Array.prototype
functions like map
, filter
, forEach
...
The code would look this way:
// #1 We turn user properties into an array of property names
// #2 Then we call "reduce" on the user property name array. Reduce
// takes a callback that will be called for every array item and it receives
// the array reference given as second parameter of "reduce" after
// the callback.
// #3 If the user is not playing, we add the user object to the resulting array
// #4 Finally, "reduce" returns the array that was passed as second argument
// and contains user objects not playing ;)
var usersNotPlaying = Object.keys(users).reduce(function (result, userName) {
if (!users[userName].isPlaying)
result.push(users[userName]);
return result;
}, []); // <-- [] is the new array which will accumulate each user not playing
Clearly using Array.prototype.reduce
concentrates both map
and filter
in a single loop and, in large array, reducing should outperform "filter+map" approach, because looping a large array twice once to filter users not playing and looping again to map them into objects again can be heavy...
Summary: I would still use filter+map over reduce when we talk about few items because sometimes readability/productivity is more important than optimization, and in our case, it seems like filter+map approach requires less explanations (self-documented code!) than reduce.
Anyway, readability/productivity is subjective to who does the actual coding...
Iterate through your users object:
var list = [];
for (var key in users) {
if (users[key].isPlaying === false) {
list.push(key);
}
}
This will give you a list of all users who have an isPlaying
property that is false
.
If you would like all of the user objects where isPlaying
is false, you can add the objects themselves instead:
var list = [];
for (var key in users) {
if (users[key].isPlaying === false) {
list.push(users[key]);
}
}
This can also be achieved using Array.prototype.reduce , which is a great all round tool. It starts with getting an array of the names:
var userNames = Object.keys(users);
To return an array just the user names where isPlaying is false, you can do:
var usersNotPlaying = userNames.reduce(function(names, name) {
if (!users[name].isPlaying) {
names.push(name);
}
return names}, []);
To return an object of user objects with their names as keys is similar:
var usersNotPlaying = userNames.reduce(function(names, name) {
if (!users[name].isPlaying) {
names[name] = users[name];
}
return names}, {});
You could also use forEach in a similar way, however since it returns undefined the object or array collecting the members must be initialised in an outer scope first:
var usersNotPlaying = {};
userNames.forEach(function(name) {
if (!users[name].isPlaying) {
usersNotPlaying[name] = users[name];
}
});
You can also use for..in :
var usersNotPlaying = {};
for (var user in users) {
if (users.hasOwnProperty(user) && !users[user].isPlaying) {
usersNotPlaying[user] = users[user];
}
}
All of the above can return an array of names, array of user objects or object of user objects. Choose whatever suits. ;-)
Please try the JS code below: set all the isPlaying to false.
var json_object={};//{"user1":{"isPlaying":"false"},"user2":{"isPlaying":"ture"}};
json_object['user1']={"isPlaying":"false"};
json_object['user2']={"isPlaying":"ture"};
console.log(json_object);
for(var key in json_object){
if(json_object[key].isPlaying === "false"){/*do what you want*/}
}
console.log(json_object);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.