jma*_*erx 13 c# asp.net linq-to-sql
我有一个 List<DateTime> dates;
我有一个班级:
class NonWorkingDay
{
public DateTime Start;
public int Days;
}
Run Code Online (Sandbox Code Playgroud)
我试图找出一种干净的方式来分组它们.
public List<NonWorkingDay> GetContiguousDates(List<DateTime> dates)
{
}
Run Code Online (Sandbox Code Playgroud)
注意:如果星期五有一个NWD而下一个是星期一,则应将它们分组.周末不被考虑.
例如,如果我有
September 3 2013
September 20 2013
September 23 2013
September 24 2013
September 30 2013
October 1 2013
Run Code Online (Sandbox Code Playgroud)
输出将是:
Start = September 3 2013, Days = 1
Start = September 20 2013, Days = 3 //weekend got skipped
Start = September 30 2013, Days = 2
Run Code Online (Sandbox Code Playgroud)
有没有办法做到这一点(没有一堆计数器变量)和使用.Select或.Where等.
谢谢
Ser*_*rvy 18
因此,我们将从这个通用迭代器函数开始.它接受一个序列和一个谓词,它接受两个项并返回一个布尔值.它将读取来自源的项目,同时项目及其前一项目将根据谓词返回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;
}
}
Run Code Online (Sandbox Code Playgroud)
我们还需要这个简单的帮助方法,它根据日期获得下一个工作日.如果你想要整合假期,那么从简单到非常困难,但这就是逻辑的发展方向.
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;
}
Run Code Online (Sandbox Code Playgroud)
现在把它们放在一起.首先我们订购日子.(如果您确保他们总是有序,您可以删除该部分.)然后我们将连续项目分组,而每个项目是前一个工作日的下一个工作日.
然后我们需要做的就是将一个IEnumerable<DateTime>连续的日期变成一个NonWorkingDay.为此,开始日期是第一个日期,并且Days是序列的计数.虽然通常使用两者First并且Count会迭代源序列两次,但我们碰巧知道返回的序列GroupWhile实际上是一个List引擎盖,因此多次迭代它不是问题,并且得到的Count甚至是O(1).
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(),
});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1335 次 |
| 最近记录: |