Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 分组连续日期_C#_Asp.net_Linq To Sql - Fatal编程技术网

C# 分组连续日期

C# 分组连续日期,c#,asp.net,linq-to-sql,C#,Asp.net,Linq To Sql,我有一个列表日期 我有一个课程: class NonWorkingDay { public DateTime Start; public int Days; } 我正试图找出一个干净的方法来将他们分组 public List<NonWorkingDay> GetContiguousDates(List<DateTime> dates) { } 产出将是: Start = September 3 2013, Days = 1 Start = Septemb

我有一个
列表日期

我有一个课程:

class NonWorkingDay
{
   public DateTime Start;
   public int Days;
}
我正试图找出一个干净的方法来将他们分组

public List<NonWorkingDay> GetContiguousDates(List<DateTime> dates)
{

}
产出将是:

Start = September 3 2013, Days = 1
Start = September 20 2013, Days = 3 //weekend got skipped
Start = September 30 2013, Days = 2
有没有办法做到这一点(没有一堆计数器变量)并使用.Select或.Where或其他什么


谢谢

因此,我们将从这个通用迭代器函数开始。它接受一个序列和一个谓词,该谓词接受两个项并返回一个布尔值。它将从源中读入项,当一个项及其上一个项基于谓词返回true时,下一个项将在“下一个组”中。如果返回false,则上一组已满,下一组启动

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> currentGroup = new List<T>() { iterator.Current };
        while (iterator.MoveNext())
        {
            if (predicate(currentGroup.Last(), iterator.Current))
                currentGroup.Add(iterator.Current);
            else
            {
                yield return currentGroup;
                currentGroup = new List<T>() { iterator.Current };
            }
        }
        yield return currentGroup;
    }
}
现在,让我们把这一切放在一起。首先我们点了几天。(如果您确保它们总是按顺序出现,您可以删除该部分。)然后我们将连续的项目分组,而每个项目都是前一个项目的下一个工作日

然后,我们需要做的就是将连续日期的
IEnumerable
转换为
非工作日
。因此,开始日期是第一个日期,
Days
是序列的计数。虽然通常使用
First
Count
会对源序列进行两次迭代,但我们碰巧知道
GroupWhile
返回的序列实际上是一个隐藏的
列表,因此多次迭代并不成问题,而获得
Count
甚至是O(1)

public IEnumerable GetContinguousDates(IEnumerable日期)
{
返回日期。订购人(d=>d)
.GroupWhile((上一个,下一个)=>GetNextWorkDay(上一个).Date==下一个.Date)
.选择(组=>新的非工作日
{
Start=group.First(),
天数=组。计数(),
});
}

您能否每周分组,然后清点组中的项目?按周分组可以在这里找到不,因为可能有2.5周的星期一到星期五在Thereahhh gotcha,所以你希望看到12.5,而不是5,5,2.5这有帮助吗@有些可能不会立即显现,但在这种情况下,它实际上只是复制/粘贴。。。
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> currentGroup = new List<T>() { iterator.Current };
        while (iterator.MoveNext())
        {
            if (predicate(currentGroup.Last(), iterator.Current))
                currentGroup.Add(iterator.Current);
            else
            {
                yield return currentGroup;
                currentGroup = new List<T>() { iterator.Current };
            }
        }
        yield return currentGroup;
    }
}
public static DateTime GetNextWorkDay(DateTime date)
{
    DateTime next = date.AddDays(1);
    if (next.DayOfWeek == DayOfWeek.Saturday)
        return next.AddDays(2);
    else if (next.DayOfWeek == DayOfWeek.Sunday)
        return next.AddDays(1);
    else
        return next;
}
public IEnumerable<NonWorkingDay> GetContiguousDates(IEnumerable<DateTime> dates)
{
    return dates.OrderBy(d => d)
            .GroupWhile((previous, next) => GetNextWorkDay(previous).Date == next.Date)
            .Select(group => new NonWorkingDay
                {
                    Start = group.First(),
                    Days = group.Count(),
                });
}