我有一个对象数组(来自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
困难:
我在想我需要对它进行排序,但由于未定义的零计数和非顺序的teamid,我不确定如何处理它。 我最初的计划是使用两个空数组(signin_count,signout_count),然后循环遍历ajax JSON并推送其中的计数(如果它是玩家团队,则取消移位)。但是,如何在那里保持teamid参考和未定义的值(因此索引保持"并行")?而且我假设那里有一个更清洁的&无论如何更好的方式(在对象数组本身上),允许我将其直接排序到结果字符串中。
尝试搜索,但没有找到任何针对双重排序考虑特定键/值对问题的内容。
对某些提示感到高兴。
答案 0 :(得分:2)
那好吧!让我们分两个阶段来做:
首先,我们必须删除不应打印的条目。你提到的等于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)
答案 1 :(得分:1)
两个步骤:
首先,迭代teamcount
并创建一个对象teamid => [0, 0, count]
。换句话说,假设所有团队成员都未决定
然后,迭代signincounts
并做两件事:将c.count
添加到result[teamid]
的相应广告位并从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)
&#13;
答案 2 :(得分:1)
我认为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)
。这意味着我们将采用我们的signincounts并将其传递给一系列函数,每个函数都会修改前一个函数的结果。因此,在发信号通知我们将要链接之后,我们将teamid
中的所有对象分组。我们得到以下对象:
{ '2': [ { status: 0, count: 1, teamid: 2 } ],
'4':
[ { status: 1, count: 3, teamid: 4 },
{ status: 0, count: 2, teamid: 4 } ] }
因为我们正在链接,所以这是传递给mapValues
的内容。根据传入的回调函数,mapValues
使用与传入的对象相同的键创建一个新对象,但具有不同的值。所以我们的结果将是一个以teamids为键的对象,这就是我相信你想要的。辅助函数定义将映射到每个teamid的内容。为每个键值对执行此辅助函数。
在辅助函数中,我们创建了一个将成为我们新的teamid映射的对象。因此,对于每个teamid,我们将返回一个看起来像{ signed_in: <Number>, signed_out: <Number>, undecided: <Number> }
的对象。我们将未决定为团队总数。然后我们从先前的结果中找到数组中的对象,该结果告诉我们该团队参加了多少,然后我们找出有多少人没有参加。我们会相应地指定signed_in
和signed_out
字段。然后我们从我们的总金额中扣除了多少个signed_in和signed_out来获取未决数。