How do I find objects with a property inside another object in JavaScript

五迷三道 提交于 2021-02-08 02:36:51

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!