【问题标题】:How to group by 15 minutes interval a json collection in Javascript如何在 Javascript 中按 15 分钟间隔对 json 集合进行分组
【发布时间】:2014-05-30 22:04:17
【问题描述】:

假设我们在 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});
});

【问题讨论】:

  • 我喜欢这样的工作。他们有一个groupBy 功能应该有所帮助。 underscorejs.org/#groupBy
  • @StéphanLascar:时间什么时候开始?是从列表中最早的时间开始每 15 分钟一次,还是从整点开始每 15 分钟一次,或者其他什么不同?
  • @StéphanLascar 在这种情况下,您是否意识到答案不是唯一的?同样,如果您查看日期19:00:00、19:10:00 和19:20:00,您将如何对它们进行分组?提供日期的顺序是否相关?
  • 您应该能够通过一点努力来解决这个问题。这是一个非常详细的示例,可以帮助您入门 -> jsfiddle.net/PM3v9/1
  • 这只是一个如何做到这一点的例子,这就是为什么我没有将它作为答案发布,我不太清楚排序规则应该是什么,但这会给你你想要的特定数据的结果,但是如果你有十次以五分钟的间隔会发生什么,应该所有这些都结束在同一个数组中,或者应该使用某种初始时间等等。这一切都非常不清楚!跨度>

标签: javascript arrays grouping


【解决方案1】:

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

您可以使用为 15 分钟间隔而不是年份设计的 groupBy 函数尝试相同的解决方案,使用 return Math.floor(+(obj.date)/(1000*60*15)); 此返回语句使用 + 将 Date 对象转换为毫秒数(自纪元以来),然后除以 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

【讨论】:

    【解决方案2】:

    此方法使用 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));
    

    【讨论】:

    • 请在您的回答中提供更多详细信息。正如目前所写的那样,很难理解您的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2011-02-17
    • 1970-01-01
    • 2015-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多