2013-07-25 68 views
5

我正在使用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如果它简化事项

+2

该对象是否从服务器返回?如果是这样,我会建议以正确的格式将数据返回给客户端,而不是在java脚本中添加解析逻辑。在服务器上运行这种类型的逻辑通常更容易,更容易测试。 – TGH

+0

是的,我从[oData](http://www.odata.org/)中的服务器获取数据。这意味着我可能甚至不需要更改服务器代码,而是使用oData的'$ count'选项(我不确定这会给我什么我想要的)。但是,我已经从先前的查询中获得了客户端中的原始数据,并且我想保存往返行程。 – Perspectivus

+0

如果我的回答确实令人满意,请将此问题标记为已回答。否则,精心制作。 – pygeek

回答

10

这看起来像一个mapreduce问题。高级解决方案如下:

  1. 重新组织列表中的成员。
  2. 数它们。

这里是一个一步一步如何对实现这一目标:通过字典列表

地图

  1. 迭代
  2. 转换时间字符串的JavaScript日期对象。
  3. 使用月份年份作为键和词典列表作为值。

这些现在按月份分组。

实施例:

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作为键值和列表长度作为其值。

实施例:

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. 

参考文献:

对于mapreduce福在JavaScript nctions看到underscore.js:
http://underscorejs.org/#map
http://underscorejs.org/#reduce

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

有关日期和DateTime对象的详细信息:
https://en.wikipedia.org/wiki/ISO_8601

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

+0

感谢@pygeek为您精心制作的答案。我不能使用jQuery以外的开源或第三方来源,所以underscorejs对我来说是不适合的。我将使用jQuery的地图和JavaScript的Array reduce。 – Perspectivus

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);