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

4

假设我们在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
@StéphanLascar:时间是从什么时候开始的?是从列表中最早的时间开始每15分钟一次,还是从整点开始每15分钟一次,或者是其他不同的方式? - Cᴏʀʏ
@Cory:时间从列表中最早的时间开始计算。 - Stéphan Lascar
1
在这种情况下,您是否意识到答案不是唯一的?如果您再次查看日期“19:00:00”、“19:10:00”和“19:20:00”,您会如何对它们进行分组?提供日期的顺序是否相关? - Elian Ebbing
1
你应该可以通过一点努力来弄清楚这个问题。这里有一个非常冗长的例子,可以帮助你入门 -> http://jsfiddle.net/PM3v9/1/ - adeneo
1
这只是一个如何做到这一点的例子,这就是为什么我没有将其发布为答案,对我来说不是很清楚排序规则应该是什么,但这将为您提供所需的特定数据结果,但如果您有十个带有五分钟间隔的时间,所有这些时间是否都应该最终出现在同一个数组中,或者是否应该使用某种初始时间等,这一切都非常不清楚! - adeneo
显示剩余6条评论
2个回答

7

tjdett的UnderscoreJS代码开始,用于一个按年份分组的问题

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

您可以尝试使用针对15分钟间隔而设计的groupBy函数来实现相同的解决方案,而不是年份,使用return Math.floor(+(obj.date)/(1000*60*15));。这个返回语句使用+将Date对象转换为毫秒数(自纪元以来),然后通过1000*60*15除以15分钟间隔,并用Math.floor()舍去小数部分。

为了使其起作用,obj.date必须是Date类型。如果您的日期只是字符串,则可能首先需要从这些字符串中解析出年、月、日、小时、分钟,然后构造一个新的Date对象

这将创建绝对的15分钟时钟块,即01:00:00-01:14:59.9999、01:15:00-01:29:59.9999等,而不是以新活动开始的15分钟。

因此,如果您想要从新数据开始的15分钟数据组,groupBy函数就需要创建一个保留当前组结束时间状态的闭包,以便启动新的组,并且它需要从按日期排序的对象中获取数据,因此需要先排序。

这听起来有点复杂,直接像这样做可能更容易一些(未经测试):

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

0

该方法接受startDate、EndDate和interval参数,将DateTime对象按照指定的时间间隔分割,并返回DateTime集合。

   const createDateTimeInterval = (startDate, endDate, interval) => {
        const dateArray = [];
        let currentDate = new Date(startDate);
        while (currentDate < new Date(endDate)) {
            var date = new Date(currentDate);
            let dateinString;
            if (date.getHours() < 12) {
                dateinString = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':' + (date.getMinutes() === 0 ? date.getMinutes() + '0' : date.getMinutes()) + ' AM';
            }
            else {
                dateinString = ((date.getHours() - 12) < 10 ? '0' + (date.getHours() - 12) : (date.getHours() - 12)) + ':' + (date.getMinutes() === 0 ? date.getMinutes() + '0' : date.getMinutes()) + ' PM';
            }
            dateArray.push({ label: dateinString, value: JSON.stringify(new Date(currentDate)) });
            currentDate = new Date(currentDate.getTime() + interval);
        }
    
        return dateArray;
    }
    const currentDate = new Date(new Date().getFullYear() + '-' + new Date().getMonth() + '-' + new Date().getDate())
    const nextDate = new Date(new Date(currentDate).getTime() + 60000 * 60 * 24)

这是当前日期的15分钟间隔。

var dateOptions = createDateTimeInterval(currentDate, nextDate, (60000 * 15));

请在您的回答中提供更多细节。目前的写法让人难以理解您的解决方案。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接