如何按月对一组对象进行分组?

时间:2013-07-25 14:08:31

标签: javascript count group-by date-range

我正在使用JavaScript。我有一个包含这种格式数据的数组:

[
        {"USER_NAME":"User1","LAST_SUCCESSFUL_CONNECT":"1373978337642"},
        {"USER_NAME":"User2","LAST_SUCCESSFUL_CONNECT":"1374515704026"},
        {"USER_NAME":"User3","LAST_SUCCESSFUL_CONNECT":"1374749782479"}
]

(上面的数字代表UTC日期/时间,以毫秒为单位。

我想按月分组(统计)数据。像这样:

[
    {"Month":"January, 2014","User_Count": 2},
    {"Month":"February, 2014","User_Count": 1},
]

如果它简化了问题,我可以使用jQuery

4 个答案:

答案 0 :(得分:13)

这看起来像map reduce问题。高级解决方案如下:

  1. 重新组织名单成员。
  2. 算上他们。
  3. 以下是实现此目标的逐步操作方法:

    地图

    1. 遍历词典列表
    2. 将datetime字符串转换为javascript datetime对象。
    3. 使用月份作为键和词典列表作为值。
    4. 现在按月份分组。

      示例:

      var l = [...];
      var o = {};
      var f = function(x){
          var dt_object = Date(x["LAST_SUCCESSFUL_CONNECT"]); // convert to datetime object
          var key = dt_object.year + '-' + dt_object.month;
      
          if (o[key] === undefined) {
              var o[key] = [];
          };
      
          o[key].push(x)
      }
      
      _.map(l, f(x)) //apply f to each member of l
      

      减少

      1. 遍历包含列表字典的新对象。
      2. 计算每个字典列表的长度。
      3. 使用count作为关键字和列表长度作为其值。
      4. 示例:

        var g = function(member_count){
            //extra logic may go here
            return member_count
        }
        
        for member in o {
            count = _.reduce(l, g(member))
            member['count'] = count
        }
        

        生成的API

        o['month-year'] //for list of dictionaries in that month
        o['month-year']['count'] //for the count of list of dictionaries in that month.
        

        参考文献:

        对于javascript中的mapreduce函数,请参阅underscore.js:
        http://underscorejs.org/#map
        http://underscorejs.org/#reduce

        Javascript日期对象:
        https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

        有关Date和DateTime对象的更多信息:
        https://en.wikipedia.org/wiki/ISO_8601

        有关map reduce的更多信息:
        https://en.wikipedia.org/wiki/MapReduce

答案 1 :(得分:1)

使用Map-reduce。以下是使用underscore.js的一个示例。它虽然有点冗长但很简单。

var data = [{
    "USER_NAME": "User1",
        "LAST_SUCCESSFUL_CONNECT": "1373978337642"
}, {
    "USER_NAME": "User2",
        "LAST_SUCCESSFUL_CONNECT": "1374515704026"
}, {
    "USER_NAME": "User3",
        "LAST_SUCCESSFUL_CONNECT": "1374749782479"
}, {
    "USER_NAME": "User4",
        "LAST_SUCCESSFUL_CONNECT": "1274749702479"
}];

var monthNames = ["January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"];

var map_result = _.map(data, function (item) {
    var d = new Date(new Number(item.LAST_SUCCESSFUL_CONNECT));
    var month = monthNames[d.getMonth()] + ", " + d.getFullYear();
    return {
        "Month": month,
        "User_Count": 1
    };
});

var result_temp = _.reduce(map_result, function (memo, item) {
    if (memo[item.Month] === undefined) {
        memo[item.Month] = item.User_Count;
    }else{
        memo[item.Month] += item.User_Count;
    }
    return memo;
},{});

//then wrap the result to the format you expected.
var result = _.map(result_temp, function(value, key){
    return {
        "Month": key,
        "User_Count": value
    };
});

console.log(result); 

答案 2 :(得分:-1)

也许这会很有用

LINQ for JavaScript
http://linqjs.codeplex.com/

答案 3 :(得分:-1)

优化方案

b = 1:3
m = 5

for(j in 1:2){
  for(i in 1:5){
    print((1-i/m)* b[j] + (i/m)* b[j+1])
  }
}