Reputation: 1443
Let's say I have the following collection of items and Dates:
ItemID: 1, Date: 10/10/2018 11:30 AM
ItemID: 1, Date: 10/10/2018 11:32 AM
ItemID: 1, Date: 10/10/2018 11:33 AM
ItemID: 1, Date: 10/10/2018 11:34 AM
ItemID: 1, Date: 10/10/2018 11:57 AM
ItemID: 2, Date: 10/10/2018 7:45 AM
ItemID: 2, Date: 10/10/2018 7:49 AM
ItemID: 3, Date: 10/10/2018 8:45 AM
ItemID: 3, Date: 10/10/2018 9:13 AM
I'd like to group by ItemID and Date but the dates I want them group by the ones that fall within 5 minutes of each other
In the data set above the following would be grouped
ItemID: 1, Date: 10/10/2018 11:30 AM <-- Grouped with Item 1
ItemID: 1, Date: 10/10/2018 11:32 AM <-- Grouped with Item 1
ItemID: 1, Date: 10/10/2018 11:33 AM <-- Grouped with Item 1
ItemID: 1, Date: 10/10/2018 11:34 AM <-- Grouped with Item 1
ItemID: 1, Date: 10/10/2018 11:57 AM <-- Not Grouped
ItemID: 2, Date: 10/10/2018 7:45 AM <-- Grouped with Item 2
ItemID: 2, Date: 10/10/2018 7:49 AM <-- Grouped with Item 2
ItemID: 3, Date: 10/10/2018 8:45 AM <-- Not Grouped
ItemID: 3, Date: 10/10/2018 9:13 AM <-- Not Grouped
The ones that are grouped are the ones that fall within 5 minutes of each other.
I know how to group them by ItemID and Date in LINQ but I'm having a hard time grouping them the way I described.
What I've tried so far:
var groupedItems = from item in items
group item by new
{
item.ItemID,
item.Date
} into g
select g;
Upvotes: 4
Views: 3299
Reputation: 2898
You can try something like this:
var groupedItems = items
.GroupBy(i => i.ItemId, (k, g) => g
.GroupBy(i => (long)new TimeSpan(i.Date.Ticks - g.Min(e => e.Date).Ticks).TotalMinutes / 5))
.SelectMany(g => g);
Upvotes: 5
Reputation: 885
My attempt at your solution:
var dates = new List<DateTime>{ ... }; // dates get initialized however your code does it...
var groups = dates.Select(d =>
d,
GroupDate = new DateTime(d.Year, d.Month, d.Day, d.Hour, (d.Minute / 5) * 5, d.Second)})
.GroupBy(g => g.GroupDate);
The math for the Minute is going to, ultimately, separate by which whole multiple of 5 the minute falls into. Another caveat is that if you don't care about day/month/year and want to group everything explicitly by minute, then scratch the new DateTime(...)
piece and replace with (d.Minute / 5) * 5
. That will group by minute regardless of day/month/year.
Hope this helps!
Upvotes: 2