11
votes

I have a list of dates and I want to group by items that are consecutive days

so if in the list I have the following dates:

Dec 31, 2013
Jan 1, 2014
Jan 2, 2014
Feb 1, 2014
Feb 2, 2014
Feb 16, 2014
Mar 13, 2014

I want to come up with a way to group this so I get:

Group 1:
Dec 31, 2013
Jan 1, 2014
Jan 2, 2014

Group 2:
Feb 1, 2014
Feb 2, 2014

Group 3:
Feb 16, 2014

Group 4: Mar 13, 2014

as you can see, the grouping is based on items that are consecutive days.

What is the best way in C#, to take this list and transform them into these groups?

2
you want month wise grouping or some other scenario you are consideringAmeya Deshpande
no . .i want grouping based on consecutive days. i have updated the question to make that more clearleora

2 Answers

12
votes

The logic of the following code is pretty straight forward, sort the list and check if the days delta is greater than 1. If it is, create a new group for it:

Create the dates for testing:

//Dates for testing
 List<DateTime> dates = new List<DateTime>()
 { 
      new DateTime(2013,12,31),
      new DateTime(2014,2,2),
     new DateTime(2014,1,1),
     new DateTime(2014,1,2),
     new DateTime(2014,2,1),               
     new DateTime(2014,2,16),
     new DateTime(2014,3,13),
 };

And create the groups:

 dates.Sort();
 //this will hold the resulted groups
 var groups = new List<List<DateTime>>();
 // the group for the first element
 var group1 = new List<DateTime>(){dates[0]};
 groups.Add(group1);

 DateTime lastDate = dates[0];
 for (int i = 1; i < dates.Count; i++)
 {
     DateTime currDate = dates[i];
     TimeSpan timeDiff = currDate - lastDate;
     //should we create a new group?
     bool isNewGroup = timeDiff.Days > 1;
     if (isNewGroup)
     {
         groups.Add(new List<DateTime>());
     }
     groups.Last().Add(currDate);
     lastDate = currDate;
 }

And the output:

enter image description here

5
votes

This should do the trick if you're looking for something very quick and dirty.

IEnumerable<DateTime> dates = ...;
var groups = dates
    .Distinct()
    .OrderBy(date => date)
    .Select((date, i) => new { date, key = date.Subtract(TimeSpan.FromDays(i)) })
    .GroupBy(tuple => tuple.key, tuple => tuple.date);