分组连续日期
- 作者: HHH-航
- 来源: 51数据库
- 2022-12-13
问题描述
我有一个 List
我有一个课程:
class NonWorkingDay
{
public DateTime Start;
public int Days;
}
我正在尝试找出一种干净的方法来将它们分组.
I am trying to figure out a clean way to group them.
public List<NonWorkingDay> GetContiguousDates(List<DateTime> dates)
{
}
注意:如果周五有 NWD,下周一是周一,则应将其分组.周末不考虑.
Note: if there is an NWD on Friday and the next is Monday they should be grouped. Weekends are not considered.
例如如果我有
September 3 2013 September 20 2013 September 23 2013 September 24 2013 September 30 2013 October 1 2013
输出将是:
Start = September 3 2013, Days = 1 Start = September 20 2013, Days = 3 //weekend got skipped Start = September 30 2013, Days = 2
有没有办法做到这一点(没有一堆计数器变量)并使用 .Select 或 .Where 之类的.
Is there any way to do this (without have a bunch of counter variables) and using .Select or .Where or something.
谢谢
推荐答案
所以,我们将从这个通用迭代器函数开始.它需要一个序列和一个接受两个项目并返回一个布尔值的谓词.它将从源中读取项目,而一个项目连同它的前一个项目,根据谓词返回 true,下一个项目将在下一组"中.如果返回false,则前一组已满,下一组开始.
So, we'll start out with this generic iterator function. It takes a sequence and a predicate that accepts two items and returns a boolean. It will read in items from the source and while an item, along with it's previous item, returns true based on the predicate, that next item will be in the "next group". If it returns false, the previous group is full and the next group is started.
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;
}
}
我们还需要这个简单的辅助方法,它根据日期获取下一个工作日.如果您还想将假期纳入其中,那么它就会从琐碎到非常困难,但这就是逻辑所在.
We'll also need this simple helper method that gets the next working day based on a date. If you want to incorporate holidays as well it goes from trivial to quite hard, but that's where the logic would go.
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;
}
现在把它们放在一起.首先我们订购天数.(如果您确保它们总是按顺序排列,您可以删除该部分.)然后我们将连续的项目分组,而每个项目都是前一个工作日的下一个工作日.
Now to put it all together. First we order the days. (If you ensure they always come in ordered you can remove that part.) Then we group the consecutive items while each item is the next work day of the previous.
然后我们需要做的就是将连续日期的 IEnumerable
Then all we need to do is turn an IEnumerable<DateTime> of consecutive dates into a NonWorkingDay. For that the start date is the first date, and Days is the count of the sequence. While normally using both First and Count would iterate the source sequence twice, we happen to know that the sequence returned by GroupWhile is actually a List under the hood, so iterating it multiple times is not a problem, and getting the Count is even 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(),
});
}
- C#通过fleck实现wss协议的WebSocket多人Web实时聊天(附源码)
- 团队城市未满足要求:MSBuildTools12.0_x86_Path 存在
- 使用 MSBuild.exe 在发布模式下构建 C# 解决方案
- 当我发布 Web 应用程序时,AfterPublish 脚本不运行
- 构建时 T4 转换的产品仅在下一个构建中使用
- ASP.NET Core Application (.NET Framework) for Windows x64 only error in project.assets.json
- 新的 .csproj 格式 - 如何将整个目录指定为“链接文件"到子目录?
- 如何将条件编译符号(DefineConstants)传递给 msbuild
- MSBuild 支持 Visual Studio 2017 RTM 中的 T4 模板
- NuGet 包还原找不到包,没有源
