如何用LINQ查找、分组并合并重叠日期时间范围以确定完整时间范围
合并分组内重叠/连续时间范围的LINQ实现
需求说明
需要处理包含重复及重叠日期时间范围的数据集,按分组合并时间范围:以分组内所有记录的最小Start时间作为合并后的起始,最大End时间作为合并后的结束。
测试数据集
public class Record { public string Name { get; set; } public DateTime Start { get; set; } public DateTime End { get; set; } } var records = new List<Record> { new Record { Name = "Group1 - A", Start = new DateTime(2024, 1, 1, 9, 0, 0), End = new DateTime(2024, 1, 1, 10, 0, 0) }, new Record { Name = "Group1 - B", Start = new DateTime(2024, 1, 1, 9, 30, 0), End = new DateTime(2024, 1, 1, 11, 0, 0) }, new Record { Name = "Group1 - C", Start = new DateTime(2024, 1, 1, 10, 30, 0), End = new DateTime(2024, 1, 1, 12, 0, 0) }, new Record { Name = "Group2 - D", Start = new DateTime(2024, 1, 1, 13, 0, 0), End = new DateTime(2024, 1, 1, 15, 0, 0) }, new Record { Name = "Group3 - E", Start = new DateTime(2024, 1, 2, 22, 0, 0), End = new DateTime(2024, 1, 2, 23, 0, 0) }, new Record { Name = "Group3 - F", Start = new DateTime(2024, 1, 2, 22, 30, 0), End = new DateTime(2024, 1, 3, 5, 0, 0) } };
预期合并结果
Group 1 – Start: 1/1/2024 9am, End: 1/1/2024 12pm
Group 2 - Start: 1/1/2024 1pm, End: 1/1/2024 3pm
Group 3 - Start: 2/1/2024 10pm, End: 3/1/2024 5am
LINQ解决方案
可以通过LINQ的GroupBy结合聚合函数实现,核心逻辑是先提取分组标识,再对每组聚合时间范围:
var mergedRecords = records // 从Name中提取分组键(如"Group1 - A"提取为"Group1") .GroupBy(record => record.Name.Split('-')[0].Trim()) // 对每个分组计算合并后的时间范围 .Select(group => new { GroupName = group.Key, MergedStart = group.Min(r => r.Start), MergedEnd = group.Max(r => r.End) }) .ToList();
结果输出示例
如果需要按预期格式输出:
foreach (var merged in mergedRecords) { Console.WriteLine($"{merged.GroupName} - Start: {merged.MergedStart:M/d/yyyy htt}, End: {merged.MergedEnd:M/d/yyyy htt}"); }
说明
- 分组键的提取逻辑可根据实际数据格式调整(比如如果分组标识不是通过
-分割,只需修改GroupBy的keySelector即可) - 该方案完全基于LINQ表达式实现,可直接适配多数.NET规则引擎的需求
内容的提问来源于stack exchange,提问作者Dean
相关产品推荐
相关产品推荐

