c# - 找到重叠的时间间隔并将它们分割成新的时间间隔
问题描述
我需要一些帮助来在 C# 中构建一个算法,该算法需要一个时间间隔列表(开始、结束),找到任何重叠的时间段并在它们的开始/结束处切割它们。然后它需要以“块”的形式合并在一起,以便最终的时间间隔只是一个周期。我会用一张图来说明它。
到目前为止我的代码。它适用于两个时间间隔,但引入第三个或更多时间间隔,它开始给出奇怪的结果:)
// Dummy objects
var d1 = new TimeSlot(DateTime.Parse("2020-05-05 13:00 PM"), DateTime.Parse("2020-05-05 13:30 PM"), "1");
var d3 = new TimeSlot(DateTime.Parse("2020-05-05 13:15 PM"), DateTime.Parse("2020-05-05 13:25 PM"), "2");
var d2 = new TimeSlot(DateTime.Parse("2020-05-05 13:05 PM"), DateTime.Parse("2020-05-05 13:20 PM"), "3");
List<TimeSlot> dates = new List<TimeSlot>();
dates.Add(d1);
dates.Add(d2);
dates.Add(d3);
List<TimeSlot> slicedDates = new List<TimeSlot>();
IEnumerable<TimeSlot> dateContainer = dates;
TimeSlot prev = dateContainer.First();
dateContainer = dateContainer.Skip(1);
foreach (TimeSlot date in dateContainer.OrderBy(x => x.StartDate))
{
var prevStartTime = prev.StartDate;
var prevEndTime = prev.EndDate;
if (date.StartDate < prev.EndDate)
{
TimeSlot leftSlice = new TimeSlot(prevStartTime, date.StartDate, prev.Name);
slicedDates.Add(leftSlice);
}
if (date.EndDate < prevEndTime)
{
TimeSlot middleSlice = new TimeSlot(date.StartDate, date.EndDate, prev.Name + "," + date.Name);
slicedDates.Add(middleSlice);
TimeSlot rightSlice = new TimeSlot(date.EndDate, prevEndTime, prev.Name);
slicedDates.Add(rightSlice);
}
prev = date;
}
并输出三个错误的时间间隔:
05-05-2020 13:00:00 => 05-05-2020 13:05:00: 1
05-05-2020 13:05:00 => 05-05-2020 13:20:00: 1,3
05-05-2020 13:05:00 => 05-05-2020 13:15:00: 3
05-05-2020 13:20:00 => 05-05-2020 13:30:00: 1
解决方案
我稍微调整了算法:
var d1 = new TimeSlot(DateTime.Parse("2020-05-05 13:00 PM"), DateTime.Parse("2020-05-05 13:30 PM"), "1");
var d3 = new TimeSlot(DateTime.Parse("2020-05-05 13:15 PM"), DateTime.Parse("2020-05-05 13:25 PM"), "2");
var d2 = new TimeSlot(DateTime.Parse("2020-05-05 13:05 PM"), DateTime.Parse("2020-05-05 13:20 PM"), "3");
List<TimeSlot> dates = new List<TimeSlot>();
dates.Add(d1);
dates.Add(d2);
dates.Add(d3);
List<TimeSlot> slicedDates = new List<TimeSlot>();
IEnumerable<TimeSlot> dateContainer = dates;
// Created an ordered list of Start & End dates.
var times = dateContainer.Select(x => x.StartDate);
times = times.Concat(dateContainer.Select(x => x.EndDate));
var orderedTimes = times.Distinct().OrderBy(x => x);
var prev = orderedTimes.First();
times = orderedTimes.Skip(1);
foreach (var time in times)
{
var names = new List<string>();
foreach (TimeSlot date in dateContainer)
{
// Add the TimeSlot if it's in range
if (prev >= date.StartDate && time <= date.EndDate)
{
names.Add(date.Name);
}
}
var name = string.Join(",",names);
TimeSlot slot = new TimeSlot(prev, time, name);
slicedDates.Add(slot);
prev = time;
}
推荐阅读
- powershell - 是否可以将 $ErrorActionPreference = 'Stop' 配置为 powershell 模块中所有功能的默认值?
- javascript - 添加 React UID 后,无法在 shallow/mount 上找到子组件
- html - 在 100%vw 的 HTML 上轻微水平滚动
- f# - 为什么 F# 类型推断不适用于类或接口?
- ios - 将图像添加为子视图时如何处理异步图像和视频?
- c# - 使用 NUnit3 控制台运行测试
- javascript - 如何将使用网络摄像头拍摄的图像发送到 api?
- c# - 如何通知 WPF DataGrid 中的一行其中一个单元格已被编程修改?
- node.js - 这个异步获取请求我做错了什么?
- python - 如何使用字典修复多线程/多处理?