admin管理员组文章数量:1315940
Let say we have a collection like this in 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' }
]
I would like to to find an elegant algorithm to group by this array by "closest" date. If a date is 15 minutes before or after a previous date, it will be pushed in the same object.
I doesn't really matter how the sub-array will be structured. The result for this entry could be:
[
[
{ 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' }
]
]
I have try without real success using 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});
});
Let say we have a collection like this in 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' }
]
I would like to to find an elegant algorithm to group by this array by "closest" date. If a date is 15 minutes before or after a previous date, it will be pushed in the same object.
I doesn't really matter how the sub-array will be structured. The result for this entry could be:
[
[
{ 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' }
]
]
I have try without real success using 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});
});
Share
Improve this question
edited Jun 17, 2017 at 1:31
ekad
14.6k26 gold badges46 silver badges48 bronze badges
asked May 30, 2014 at 22:04
Stéphan LascarStéphan Lascar
1851 silver badge5 bronze badges
10
-
I'm a fan of underscore for work like this. They have a
groupBy
function that should help. underscorejs/#groupBy – chris vdp Commented May 30, 2014 at 22:08 - 1 @StéphanLascar: When does time start? Is it every 15 minutes from the earliest time in the list, or 15 minutes from the top of the hour, or something different? – Cᴏʀʏ Commented May 30, 2014 at 22:15
-
1
@StéphanLascar In that case, do you realize that the answer is not unique? Again, if you look at the dates
19:00:00
,19:10:00
and19:20:00
, how would you group them? Is the order in which the dates are provided relevant? – Elian Ebbing Commented May 30, 2014 at 22:18 - 1 You should be able to figure this out with a little effort. Here's a really verbose example to get you started -> jsfiddle/PM3v9/1 – adeneo Commented May 30, 2014 at 22:20
- 1 It's just an example of how to do this, which is why I didn't post it as an answer, it's not really clear to me what the sorting rules should be, but this will give you the result you wanted for that particular data, but what should happen if you have ten times with five minute intervals, should all of them end up in the same array or should some sort of initial time be used etc. It's all very unclear ! – adeneo Commented May 30, 2014 at 22:27
2 Answers
Reset to default 7Starting with the 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();
You could try this same solution with a groupBy function designed for 15 minute intervals instead of years, with return Math.floor(+(obj.date)/(1000*60*15));
This return statement uses +
to convert the Date object to a number of milliseconds (since epoch), and then divides by 1000*60*15 for 15 minute intervals with Math.floor()
discarding the fraction.
For that to work, obj.date must be type Date. If your dates are just strings, you may first need to parse the year, month, day, hour, minutes out of those strings and then construct a new Date object.
This will create absolute 15 minute clock blocks, i.e. 01:00:00-01:14:59.9999, 01:15:00-01:29:59.9999; not 15 minutes that begin with new activity.
So if you want a group of 15 minutes of data that starts with new data, the groupBy function would need to be created with a closure retaining state of when the current group ends so that new groups could be started, and it would need to be fed from objects sorted by date, so that a sort needs to happen first.
That sounds Rube-Goldbergish, and might be easier to do directly like this (untested):
fixDates(objArray); // a function you'll write to turn your date strings into Date objects
function pareDates(a,b){ return (+a.date)-(+b.date); }
objArray.sort(pareDates); // 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
This method takes startDate,EndDate and interval to break DateTime and return DateTime Collection on specified interval
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)
This is the 15 minutes interval on a current date.
var dateOptions = createDateTimeInterval(currentDate, nextDate, (60000 * 15));
本文标签: arraysHow to group by 15 minutes interval a json collection in JavascriptStack Overflow
版权声明:本文标题:arrays - How to group by 15 minutes interval a json collection in Javascript - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741984852a2408614.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论