You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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);
        });
});

代码说明

  1. 排序:先对所有Schedule按StartingDate排序,保证每个分组内的项是按时间顺序排列的,避免因顺序混乱导致验证错误。
  2. 分组:按DayCode将Schedule分成多个组,每组单独验证。
  3. 分组验证:
    • 若分组只有1个项,直接返回true;
    • 用Take(items.Count -1)取分组中除最后一项外的所有项,Skip(1)取分组中从第二项开始的所有项,通过Zip将这两个序列配对成相邻的前后项;
    • 对每一对前后项验证时间连续性,最后用All确保所有配对都满足条件,只要有一对不满足,整个分组就验证失败。

原代码的问题点

  • approved变量会被后续循环覆盖,只要有一个配对满足就设为true,但实际需要所有配对都满足才返回true;
  • 没有处理验证失败的情况,一旦有配对不满足,应该直接返回false,而不是继续循环。

内容的提问来源于stack exchange,提问作者codetime

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 11:27:34