问题
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?
回答1:
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]);
Using 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 (i.e. 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...
回答2:
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]);
}
}
回答3:
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. ;-)
回答4:
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);
来源:https://stackoverflow.com/questions/31769376/how-do-i-find-objects-with-a-property-inside-another-object-in-javascript