[英]Javascript sort array of objects on key
我有一个对象数组(来自ajax / PDO调用),如下所示:
signincounts: [{ status: 1
count: 3
teamid: 4
},{
status: 0
count: 1
teamid: 2
},{
status: 0
count: 2
teamid: 4
}]
这些对象代表登录特定事件的用户数:
另外,我还有以下信息:
teamcount : {
2: 5
4: 6
}
我现在想在Javascript中对它进行排序,以显示登录状态,如下所示:
小组2:登录/退出/尚未决定
小组4:已登录/已退出/尚未决定
在这种情况下,将是:
小组2:0/1/4
小组4:3/2/1
难点:
我当时想我需要对它进行排序,但是由于未定义的零计数和不连续的团队标识,因此不确定如何进行处理。 我最初的计划是使用两个空数组(signin_count,signout_count),然后遍历ajax JSON并将计数推入其中(如果是玩家团队,则不移位)。 但是,如何在其中保留teamid参考和未定义的值(因此索引保持“平行”)? 而且我假设无论如何(在对象数组级别本身)有一种更干净,更好的方法,这将允许我将其直接排序到结果字符串中。
也尝试过搜索,但没有找到有关考虑特定键/值对的双重排序问题。
对于某些指示会很高兴。
好吧! 让我们分两个阶段进行操作:
首先,我们必须消除不应打印的条目。 您提到的计数等于0
:
data = data.filter(function(entry) { entry.count > 0 })
现在,将打印data
中所有剩余的条目,我们可以将它们按所需顺序排序。 您提到了两个约束:
使用具有以下签名的比较函数来调用Javascript Array
对象的.sort()
方法:
function compare(a, b) returns Number
返回的Number
解释如下:
compare
返回< 0
,则a
在b
之前 compare
返回> 0
,则b
在a
之前 compare
返回0
,则没关系(通常遵循先前的顺序) 因此,让我们编写一个可以对数据进行排序的compare
函数:
function compare(a, b) {
// The special USER_TEAM_ID goes before any other element:
if (a.teamId === USER_TEAM_ID) return -1
// For any other case:
return a.teamId - b.teamId // invert these to reverse the sort
}
现在您可以致电:
data.sort(compare)
两步:
首先,迭代teamcount
并创建一个对象teamid => [0, 0, count]
。 换句话说,假设所有团队成员都不确定
然后,迭代signincounts
并执行两件事:将c.count
添加到result[teamid]
的相应插槽中,并从result[teamid][undecided]
减去c.count
result[teamid][undecided]
这为您提供了所需的统计信息,最终的排序和输出留给读者。
码:
data = { signincounts: [{ status: 1, count: 3, teamid: 4 }, { status: 0, count: 1, teamid: 2 }, { status: 0, count: 2, teamid: 4 }] , teamcount: { 2: 5, 4: 6 } }; res = {} Object.keys(data.teamcount).forEach(teamid => res[teamid] = [0, 0, data.teamcount[teamid]]); data.signincounts.forEach(c => { res[c.teamid][c.status] = c.count; res[c.teamid][2] -= c.count; }); console.log(res)
我认为lodash在这里会为您服务。
var signincounts = [{ status: 1, count: 3, teamid: 4 },{ status: 0, count: 1, teamid: 2 },{ status: 0, count: 2, teamid: 4 }], teamcount = { 2: 5, 4: 6 }; var result = _.chain(signincounts) .groupBy('teamid') .mapValues(mapTeams).value(); console.log(result); // helper function for mapping from grouped data function mapTeams(teamData, teamid) { var team = {}; team.undecided = teamcount[teamid]; var signed_in = _.find(teamData, {status: 1}), // gets the object that tells us how many are signed in signed_out = _.find(teamData, {status: 0}); // gets the object that tells us how many are signed out team.signed_in = (signed_in && signed_in.count) ? signed_in.count : 0; // guard against undefined team.signed_out = (signed_out && signed_out.count) ? signed_out.count : 0; // guard against undefined team.undecided -= (team.signed_in + team.signed_out); return team; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.2/lodash.min.js"></script>
所以这就是正在发生的事情。 首先我们调用_.chain(signincounts)
。 这意味着我们将采用登录计数,并将其通过一系列函数进行传递,每个函数都会修改前一个函数的结果。 因此,在发出我们要链接的信号后,我们按其teamid
将数组中的所有对象teamid
。 我们得到以下对象:
{ '2': [ { status: 0, count: 1, teamid: 2 } ],
'4':
[ { status: 1, count: 3, teamid: 4 },
{ status: 0, count: 2, teamid: 4 } ] }
因为我们正在链接,所以这就是传递给mapValues
。 mapValues
根据传入的回调函数创建一个具有与传入的对象相同的键,但具有不同值的新对象。因此,我们的结果将是一个以小队号作为键的对象,这就是我所希望的。 helper函数定义将映射到每个teamid的内容。 对于每个键值对执行此辅助函数。
在helper函数内部,我们创建一个对象,该对象将成为新的teamid映射。 因此,对于每个teamid,我们将返回一个看起来像{ signed_in: <Number>, signed_out: <Number>, undecided: <Number> }
。 我们未定为团队总数。 然后,我们从先前的结果中找到数组中的对象,该结果告诉我们该团队有多少人参加,然后我们找出有多少人没有参加。 我们相应地分配了signed_in
和signed_out
字段。 然后,我们从总数中减去signed_in和signed_out的数目,以获得未定的计数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.