Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C#, what is the best way to group consecutive dates in a list?

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?

like image 510
leora Avatar asked Dec 10 '14 05:12

leora


People also ask

What is '~' in C language?

In mathematics, the tilde often represents approximation, especially when used in duplicate, and is sometimes called the "equivalency sign." In regular expressions, the tilde is used as an operator in pattern matching, and in C programming, it is used as a bitwise operator representing a unary negation (i.e., "bitwise ...

What is operators in C?

C operators are one of the features in C which has symbols that can be used to perform mathematical, relational, bitwise, conditional, or logical manipulations. The C programming language has a lot of built-in operators to perform various tasks as per the need of the program.


2 Answers

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);
like image 71
Timothy Shields Avatar answered Sep 16 '22 13:09

Timothy Shields


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

like image 22
Avi Turner Avatar answered Sep 19 '22 13:09

Avi Turner