Sté*_*car 2 javascript arrays grouping
假设我们在 Javascript 中有一个这样的集合:
[
{ date: 'Fri, 02 May 2014 19:05:00 GMT', value:'abc' },
{ date: 'Fri, 02 May 2014 23:43:00 GMT', value:'jkl' },
{ date: 'Fri, 02 May 2014 19:01:00 GMT', value:'def' },
{ date: 'Fri, 02 May 2014 19:09:00 GMT', value:'ghi' },
{ date: 'Fri, 02 May 2014 23:54:00 GMT', value:'mno' }
]
Run Code Online (Sandbox Code Playgroud)
我想找到一个优雅的算法来按“最近”日期按这个数组分组。如果日期在前一个日期之前或之后 15 分钟,它将被推送到同一个对象中。
我并不关心子数组的结构。此条目的结果可能是:
[
[
{ date: 'Fri, 02 May 2014 19:05:00 GMT', value:'abc' },
{ date: 'Fri, 02 May 2014 19:01:00 GMT', value:'def' },
{ date: 'Fri, 02 May 2014 19:09:00 GMT', value:'ghi' }
], [
{ date: 'Fri, 02 May 2014 23:43:00 GMT', value:'jkl' },
{ date: 'Fri, 02 May 2014 23:54:00 GMT', value:'mno' }
]
]
Run Code Online (Sandbox Code Playgroud)
我尝试使用 underscore.js 没有真正成功:
_.map(logs_by_date, function(group, date) {
return _.reduce(group, function(memo, elem) {
var moment = get_moment(elem);
memo[moment].push(elem);
return memo;
}, { 'date': date});
});
Run Code Online (Sandbox Code Playgroud)
从 tjdett 的 UnderscoreJS 代码开始,逐年提问:
var dateGroups = _.chain(objarray)
.groupBy(function(obj) { return obj.date.getFullYear(); })
.sortBy(function(v, k) { return k; })
.value();
Run Code Online (Sandbox Code Playgroud)
您可以使用为 15 分钟而不是年设计的 groupBy 函数尝试相同的解决方案,return Math.floor(+(obj.date)/(1000*60*15));此返回语句用于+将 Date 对象转换为毫秒数(自纪元以来),然后除以 1000*60*15 为 15Math.floor()丢弃分数的分钟间隔。
为此,obj.date 必须是 Date 类型。如果您的日期只是字符串,您可能首先需要从这些字符串中解析年、月、日、小时、分钟,然后构造一个新的 Date 对象。
这将创建绝对 15 分钟的时钟块,即 01:00:00-01:14:59.9999, 01:15:00-01:29:59.9999; 不是以新活动开始的 15 分钟。
因此,如果您想要一组以新数据开头的 15 分钟数据,则需要创建 groupBy 函数,并保留当前组结束时的闭包状态,以便可以启动新组,并且需要从按日期排序的对象馈送,因此需要先进行排序。
这听起来像 Rube-Goldbergish,可能更容易像这样直接执行(未经测试):
fixDates(objArray); // a function you'll write to turn your date strings into Date objects
function compareDates(a,b){ return (+a.date)-(+b.date); }
objArray.sort(compareDates); // sorts in place, array is changed
var groups = [], g=[], d=0;
for (var gx=+objArray[0].date+15*60*1000,i=0,l=objArray.length; i<l; ++i){
d = +(objArray[i].date);
if (d>gx){
groups.push(g);
g = [];
gx = +objArray[i].date+15*60*1000;
}
g.push(objArray[i]);
}
groups.push(g); // include last group otherwise unpushed
// result in groups
Run Code Online (Sandbox Code Playgroud)