问题描述
我有一个包含所有用户的对象,如下所示:var users = {user1:{}, user2:{}}
,并且每个用户都有一个 isPlaying 属性.如何让所有使用 isPlaying 为 false 的用户?
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?
推荐答案
你应该使用 Object.keys
、Array.prototype.filter
和 Array.prototype.map
:
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];
});
如果使用 ECMA-Script 6 完成,您可以使用箭头函数:
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
正如@RobG 指出的,你也可以使用 Array.prototype.reduce
.
虽然我不想重叠他的新答案和自己的答案,但我相信 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.
基本上,如果你返回一个对象而不是一个数组,问题是另一个调用者(即调用一个执行所谓的reduce
的函数)可能需要调用再次reduce
执行新的操作,而一个数组已经准备好流畅地调用其他Array.prototype
函数,如map
、filter
>, forEach
...
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
...
代码看起来像这样:
// #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
显然使用 Array.prototype.reduce
将 map
和 filter
集中在一个循环中,并且在大数组中,reduce 应该优于"filter+map" 的方法,因为循环一个大数组两次以过滤不播放的用户并再次循环以再次将它们映射到对象可能很重...
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...
总结:当我们谈论很少的项目时,我仍然会使用filter+map而不是reduce,因为有时可读性/生产力比优化更重要,在我们的例子中,看起来 filter+map 方法比 reduce 需要更少的解释(自我记录的代码!).
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...
这篇关于如何在 JavaScript 中的另一个对象中找到具有属性的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!