Javascript在键上排序对象数组

时间:2016-09-26 21:45:17

标签: javascript arrays sorting

我有一个对象数组(来自ajax / PDO调用),如下所示:

signincounts: [{ status: 1
   count:  3
   teamid: 4
 },{
   status: 0
   count:  1
   teamid: 2
 },{
   status: 0
   count:  2
   teamid: 4
}]

这些对象表示为特定事件登录的用户数:

  • status = 1(已登录,将参加)
  • status = 0(退出,不会参加)
  • count = x登录/退出的人数
  • teamid = y他们所属的团队

此外,我还有以下信息:

teamcount : {
    2: 5
    4: 6
}
  • teamid:玩家总数

我现在想在Javascript中对此进行排序以显示如下的登录统计信息:

  

团队2:已登录/已退出/尚未决定

     第4组:登录/退出/尚未决定

在这种情况下:

  

团队2:0/1/4

     

团队4:3/2/1

困难:

  • teamids是唯一的,但不一定是顺序的
  • 如果状态的计数为零,则它不是返回的JSON
  • 的一部分
  • 对象不一定按顺序
  • 可以有两到几十个团队
  • 字符串输出应按teamid排序,查看者团队位于顶部(还有一个附加变量playerteamid,可用于简单检查)

我在想我需要对它进行排序,但由于未定义的零计数和非顺序的teamid,我不确定如何处理它。 我最初的计划是使用两个空数组(signin_count,signout_count),然后循环遍历ajax JSON并推送其中的计数(如果它是玩家团队,则取消移位)。但是,如何在那里保持teamid参考和未定义的值(因此索引保持"并行")?而且我假设那里有一个更清洁的&无论如何更好的方式(在对象数组本身上),允许我将其直接排序到结果字符串中。

尝试搜索,但没有找到任何针对双重排序考虑特定键/值对问题的内容。

对某些提示感到高兴。

3 个答案:

答案 0 :(得分:2)

那好吧!让我们分两个阶段来做:

过滤阶段

首先,我们必须删除不应打印的条目。你提到的等于0

的计数
data = data.filter(function(entry) { entry.count > 0 })

排序阶段

现在要打印data中的所有剩余条目,我们可以将它们按所需顺序排序。你提到了两个约束:

  • 应首先显示较低的团队ID
  • 特定的团队ID应始终显示在顶部

使用带有此签名的比较函数调用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]

这为您提供了所需的统计数据,最终排序和输出留给了读者。

代码:

&#13;
&#13;
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;
&#13;
&#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_insigned_out字段。然后我们从我们的总金额中扣除了多少个signed_in和signed_out来获取未决数。