2

Below is my List

List<DateTime> ls_date =new List<DateTime>()
ls_date.Add("2013-12-02")
ls_date.Add("2013-12-03")
ls_date.Add("2013-12-04")
ls_date.Add("2013-12-05")
ls_date.Add("2013-12-08")
ls_date.Add("2013-12-12")
ls_date.Add("2013-12-13")
ls_date.Add("2013-12-14")

I want to group continuous date and select start and end date of that group

Output:

"2013-12-02"-"2013-12-05"
"2013-12-08"-"2013-12-08"
"2013-12-12"-"2013-12-14"

My try:

public class sampleWithIntervals
{
 public DateTime startDate;
 public DateTime endDate;
}
    var data = ls_date
            .Select((s, i) => new { sample = s, index = i })                
            .GroupBy(si => new { date = si.sample.Date.AddDays(-si.index) })                
            .Select(g => new sampleWithIntervals()
            {
                startDate = g.Min(s => s.sample.Date),
                endDate = g.Max(s => s.sample.Date)

            });

How can i achieve this?

balaji
  • 1,236
  • 2
  • 18
  • 28
  • You could start with my (http://codereview.stackexchange.com/questions/6512/grouping-by-sequence-in-linq) function or one of the answers. – MPelletier Nov 25 '13 at 18:08
  • `List ls_date =new List(); ls_date.Add("2013-12-02");` will not compile: strings aren't `DateTime`s unless they're parsed to be. – Tim S. Nov 25 '13 at 18:28
  • sorry.i'm converting and adding into list – balaji Nov 25 '13 at 18:33

1 Answers1

3

Here is a helper function that groups items based on a function that takes the current and previous items determines if that item should be in the existing group, or a new group:

public static IEnumerable<IEnumerable<T>> GroupWhile<T>(
    this IEnumerable<T> source, Func<T, T, bool> predicate)
{
    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
            yield break;

        List<T> list = new List<T>() { iterator.Current };

        T previous = iterator.Current;

        while (iterator.MoveNext())
        {
            if (predicate(previous, iterator.Current))
            {
                list.Add(iterator.Current);
            }
            else
            {
                yield return list;
                list = new List<T>() { iterator.Current };
            }

            previous = iterator.Current;
        }
        yield return list;
    }
}

Now you can write:

var intervals = dates.GroupWhile((prev, next) => 
        prev.Date.AddDays(1) == next.Date)
    .Select(g => new sampleWithIntervals()
    {
        startDate = g.Min(s => s.Date),
        endDate = g.Max(s => s.Date)
    });
Servy
  • 202,030
  • 26
  • 332
  • 449
  • i'm not getting any list as result – balaji Nov 25 '13 at 18:17
  • @balaji Works just fine in a test I wrote. Perhaps your input data set is empty. – Servy Nov 25 '13 at 18:20
  • i've defined this static method inside a static class. Is that correct? – balaji Nov 25 '13 at 18:27
  • It would be good if you edit and post full sample code of yours – balaji Nov 25 '13 at 18:35
  • @balaji Yes, it should be in a static class. If it compiles, then clearly that's not an issue. If you're getting an empty result set then the *only* option is that you have an empty data source. You only need to create an array with `DateTime.Today` in it to see it create a group from it. – Servy Nov 25 '13 at 18:39