将连续日期组合到范围中

RRR*_*RRR 3 c# linq c#-4.0

我有一个对象列表

public class sample
{
 public DateTime Date;
 public string content;
}
Run Code Online (Sandbox Code Playgroud)

我希望能够创建一个新对象列表

public class sampleWithIntervals
{
 public DateTime startDate;
 public DateTime endDate;
 public string content;
}
Run Code Online (Sandbox Code Playgroud)

应根据内容将样本对象分组为间隔.间隔可以仅包括原始样本列表中包含的那些日期.我不知道如何在Linq做到这一点.

样本数据:

{"10/1/2013", "x"}
{"10/2/2013", "x"}
{"10/2/2013", "y"}
{"10/3/2013", "x"}
{"10/3/2013", "y"}
{"10/10/2013", "x"}
{"10/11/2013", "x"}
{"10/15/2013", "y"}
{"10/16/2013", "y"}
{"10/20/2013", "y"}

This should give me 
{"10/1/2013","10/3/2013", "x"}
{"10/2/2013","10/3/2013", "y"}
{"10/10/2013","10/11/2013", "x"}
{"10/15/2013","10/16/2013", "y"}
{"10/20/2013","10/20/2013", "y"}
Run Code Online (Sandbox Code Playgroud)

D S*_*ley 8

这是一种非Linq方式:

List<sampleWithIntervals> groups = new List<sampleWithIntervals>();  
sampleWithIntervals curGroup = null;

foreach(sample s in samples.OrderBy(sa => sa.content).ThenBy(sa => sa.Date))
{
    if(curGroup == null || // first group
        s.Date != curGroup.endDate.AddDays(1) ||
        s.content != curGroup.content   // new group
      ) 
    {
        curGroup = new sampleWithIntervals() {startDate = s.Date, endDate = s.Date, content = s.content};
        groups.Add(curGroup);
    }
    else
    {
        // add to current group
        curGroup.endDate = s.Date;
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以使用一个把日期减去索引的项目分组的技巧来对Linq这样做,以便对连续的项目进行分组:

samples.OrderBy(s => s.content)   
       .ThenBy(s => s.Date)
       // select each item with its index
       .Select ((s, i) => new {sample = s, index = i})  
       // group by date miuns index to group consecutive items
       .GroupBy(si => new {date = si.sample.Date.AddDays(-si.index), content = si.sample.content})  
       // get the min, max, and content of each group
       .Select(g => new sampleWithIntervals() {
                        startDate = g.Min(s => s.sample.Date), 
                        endDate = g.Max(s => s.sample.Date), 
                        content = g.First().sample.content
                        })
Run Code Online (Sandbox Code Playgroud)