如何用LINQ验证GroupBy分组中Schedule连续项的时间属性?
Fluent Validation:按DayCode分组验证Schedule时间连续性的LINQ实现
我正在编写Fluent Validation逻辑,需要对List<Schedule>按DayCode分组后做验证:所有分组中,后一个对象的StartingDate必须等于前一个对象的EndingDate加1秒。
Schedule对象示例:
Schedule = [ { Daycode = "1", StartingDate = "2023-07-12T00:00:00.000Z", EndingDate = "2023-07-12T08:00:00.000Z" }, { Daycode = "1", StartingDate = "2023-07-12T08:00:01.000Z", EndingDate = "2023-07-12T23:59:59.000Z" } ]
边界情况
- 分组仅含1个项时,无需验证,直接返回true
- 分组项数为奇数时,仅验证相邻项,最后一项无需处理
我希望用纯LINQ实现并返回布尔值,目前的尝试代码如下,但逻辑存在问题:
RuleFor(c => c.Tele.MustAsync(async (tele, cancellation) => { var scheduleSorted = tele.Schedule.OrderBy(r => r.StartingDate); var scheduleGrouped = scheduleSorted.GroupBy(r => r.DayCode); var approved = false; foreach(var group in scheduleGrouped) { var groupList = group.ToList(); if(groupList .Count() == 1) approved = true; else { for (int i = 0; i < groupList.Count; i++) { var currentElement = groupList[i]; if (i < groupList.Count -1) { var nextElement = groupList[i+1]; if (currentElement.EndingDate.AddSeconds(1) == nextElement.StartingDate) { approved = true; } } } } return approved; }
解决方案:纯LINQ实现
核心思路是通过LINQ的分组、配对相邻项、批量验证三个步骤完成,代码如下:
RuleFor(c => c.Tele).MustAsync(async (tele, cancellation) => { return tele.Schedule // 先按开始时间排序,确保分组内的项是时间顺序 .OrderBy(s => s.StartingDate) // 按DayCode分组 .GroupBy(s => s.DayCode) // 验证所有分组都符合规则 .All(group => { var items = group.ToList(); // 单个项直接通过验证 if (items.Count <= 1) return true; // 配对相邻的前后项:前n-1项和从第2项开始的所有项 return items.Take(items.Count - 1) .Zip(items.Skip(1), (prevItem, nextItem) => // 验证前项结束时间+1秒等于后项开始时间 prevItem.EndingDate.AddSeconds(1) == nextItem.StartingDate) // 确保所有配对都满足条件 .All(isValid => isValid); }); });
代码说明
- 排序:先对所有Schedule按
StartingDate排序,保证每个分组内的项是按时间顺序排列的,避免因顺序混乱导致验证错误。 - 分组:按
DayCode将Schedule分成多个组,每组单独验证。 - 分组验证:
- 若分组只有1个项,直接返回true;
- 用
Take(items.Count -1)取分组中除最后一项外的所有项,Skip(1)取分组中从第二项开始的所有项,通过Zip将这两个序列配对成相邻的前后项; - 对每一对前后项验证时间连续性,最后用
All确保所有配对都满足条件,只要有一对不满足,整个分组就验证失败。
原代码的问题点
approved变量会被后续循环覆盖,只要有一个配对满足就设为true,但实际需要所有配对都满足才返回true;- 没有处理验证失败的情况,一旦有配对不满足,应该直接返回false,而不是继续循环。
内容的提问来源于stack exchange,提问作者codetime
相关产品推荐
相关产品推荐

