这有点难以解释。我有一个包含日程安排信息的数据表。每行代表一个包含开始日期/时间和结束日期/时间的计划。我需要对这些进行分组,以使整个开始时间与给定的持续时间匹配。
例如,我的数据表中可能包含以下内容:
Schedule1: Start - 9:00AM, End - 9:30AM
Schedule2: Start - 9:30AM, End - 10:00AM
Schedule3: Start - 10:00AM, End - 10:30AM
Schedule4: Start - 10:30AM, End - 11:00AM
现在,如果我的持续时间值为60分钟,那么我需要能够产生以下输出:
Block1: Schedules(1,2): 9:00AM - 10:00AM
Block2: Schedules(2,3): 9:30AM - 10:30AM
Block3: Schedules(3,4): 10:00AM - 11:00AM
但是如果持续时间是120分钟,那么我需要产生以下内容:
Block1: Schedules(1,2,3,4): 9:00AM - 11:00AM
如果需要澄清,请告诉我。我需要在C#中编写一个方法来执行此转换。请帮助我,因为我已经坚持了很长时间。
答案 0 :(得分:1)
您是否选择在C#或SQL中执行此操作,部分取决于数据的规模。假设我们使用相对较少的时间范围(比如< 10),那么将所有时间都拉入内存并在C#中找到块是合理的。
鉴于以下类别:
public class Schedule {
public int ID { get; set; }
public DateTime Start { get; set; }
public DateTime End { get; set; }
public int Minutes { get; set; }
}
public class ScheduleBlock : Schedule {
public List<Schedule> Schedules { get; set; }
}
这是一个简单的算法,迭代地将范围组合在一起,直到表示每个可能的组合(注意组合的数量增长为O(n ^ 2)):
public List<ScheduleBlock> CombineAllSchedules(List<Schedule> origschedules, out int added)
{
added = 0;
var schedules = new List<ScheduleBlock>();
foreach (var s in origschedules) {
var snew = new ScheduleBlock { Schedules = new List<Schedule> { s }, Start = s.Start, End = s.End, Minutes = s.Minutes };
schedules.Add(snew);
}
for (var i = 0; i < schedules.Count; i++) {
var s = schedules[i];
var matchstart = schedules.Where (s2 => s2.End == s.Start).ToList();
var matchend = schedules.Where (s2 => s2.Start == s.End).ToList();
foreach (var s2 in matchstart) {
var newschedule = CombineSchedules(s2, s);
if (!schedules.Any (sc => sc.Start == newschedule.Start && sc.End == newschedule.End)) {
schedules.Add(newschedule);
added++;
}
}
foreach (var s2 in matchend) {
var newschedule = CombineSchedules(s, s2);
if (!schedules.Any (sc => sc.Start == newschedule.Start && sc.End == newschedule.End)) {
schedules.Add(newschedule);
added++;
}
}
}
return schedules;
}
public ScheduleBlock CombineSchedules(Schedule s1, Schedule s2)
{
var schedules = new List<Schedule>();
if (s1 is ScheduleBlock) schedules.AddRange(((ScheduleBlock)s1).Schedules);
else schedules.Add(s1);
if (s2 is ScheduleBlock) schedules.AddRange(((ScheduleBlock)s2).Schedules);
else schedules.Add(s2);
var s = new ScheduleBlock {
Schedules = schedules,
Start = s1.Start, End = s2.End, Minutes = s1.Minutes + s2.Minutes
};
return s;
}
将组合放在一起后,查询它们并获得特定长度(如60分钟或120分钟)是一件简单的事情:
public List<ScheduleBlock> FindBlocks(List<Schedule> schedules, int blockLength)
{
int added;
var combinedSchedules = CombineAllSchedules(schedules, out added);
var result = combinedSchedules.Where (s => s.Minutes == blockLength).ToList();
return result;
}
有了这个算法,你可以做这样的事情,例如获得你正在寻找的输出:
var schedules = new List<Schedule> {
new Schedule { ID = 1, Start = DateTime.Parse("09:00 AM"), End = DateTime.Parse("09:30 AM") },
new Schedule { ID = 2, Start = DateTime.Parse("09:30 AM"), End = DateTime.Parse("10:00 AM") },
new Schedule { ID = 3, Start = DateTime.Parse("10:00 AM"), End = DateTime.Parse("10:30 AM") },
new Schedule { ID = 4, Start = DateTime.Parse("10:30 AM"), End = DateTime.Parse("11:00 AM") },
};
foreach (var s in schedules) {
s.Minutes = (int)(s.End - s.Start).TotalMinutes;
}
Console.WriteLine("60 Minute Blocks");
Console.WriteLine("----------------");
var blocks = FindBlocks(schedules, 60);
var blockId = 1;
foreach (var block in blocks) {
var output = "Block" + blockId +
": Schedules(" + string.Join(",", block.Schedules.Select (s => s.ID)) + "): " +
block.Start.ToString("h:mmtt") + " - " + block.End.ToString("h:mmtt");
Console.WriteLine(output);
blockId++;
}
Console.WriteLine();
Console.WriteLine("120 Minute Blocks");
Console.WriteLine("----------------");
blocks = FindBlocks(schedules, 120);
blockId = 1;
foreach (var block in blocks) {
var output = "Block" + blockId +
": Schedules(" + string.Join(",", block.Schedules.Select (s => s.ID)) + "): " +
block.Start.ToString("h:mmtt") + " - " + block.End.ToString("h:mmtt");
Console.WriteLine(output);
blockId++;
}
示例结果:
60 Minute Blocks
----------------
Block1: Schedules(1,2): 9:00AM - 10:00AM
Block2: Schedules(2,3): 9:30AM - 10:30AM
Block3: Schedules(3,4): 10:00AM - 11:00AM
120 Minute Blocks
----------------
Block1: Schedules(1,2,3,4): 9:00AM - 11:00AM