如何在Javascript中按15分钟间隔对json集合进行分组

时间:2014-05-30 22:04:17

标签: 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' }
]

我想找到一个优雅的算法,通过这个数组分组,最近的"日期。如果日期是前一个日期之前或之后的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' }
    ]
]

我使用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});
});

1 个答案:

答案 0 :(得分:4)

UnderscoreJS code from tjdett for a group-by-year question开始:

var dateGroups = _.chain(objarray)
                  .groupBy(function(obj) { return obj.date.getFullYear(); })
                  .sortBy(function(v, k) { return k; })
                  .value();

您可以尝试使用groupBy函数设置15分钟而不是几年的同一解决方案return Math.floor(+(obj.date)/(1000*60*15));此返回语句使用+将Date对象转换为毫秒数(自epoch起) ),然后除以1000 * 60 * 15,间隔15分钟,Math.floor()丢弃分数。

要使其工作,obj.date必须是Date类型。如果您的日期只是字符串,则可能需要先parse the year, month, day, hour, minutes out of those strings and then construct a new Date object

这将创建绝对的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