这应该给你一个有效范围的列表。这是没有优化的第一个简单划痕。代码应该用评论来解释自己。如果您想获得“有效”时间量,只需在结果中添加范围Console.WriteLine("{0} valid hours", valid.Sum(r => (r.End - r.Start).TotalHours));
它是在假设下编码的,范围经过验证(开始<结束)!
类用于存储时间范围:
class TimeRange
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
public TimeRange()
{
}
public TimeRange(TimeSpan todayStart, TimeSpan todayEnd)
{
Start = DateTime.Today + todayStart;
End = DateTime.Today + todayEnd;
}
}
Testcode:
static void Main(string[] args)
{
var main = new TimeRange(new TimeSpan(4, 0, 0), new TimeSpan(14, 0, 0));
var except = new List<TimeRange>{
new TimeRange(new TimeSpan(3, 0, 0), new TimeSpan(6, 0, 0)),
new TimeRange(new TimeSpan(5, 0, 0), new TimeSpan(9, 0, 0)),
new TimeRange(new TimeSpan(12, 0, 0), new TimeSpan(13, 0, 0))
};
var valid = GetFreeSlots(main, except);
}
算法:
private static List<TimeRange> GetFreeSlots(TimeRange main, List<TimeRange> except)
{
// 1. ignore Ranges outside
except = except.Where(e => main.Start < e.End && main.End > e.Start).ToList();
// 2. shrink the main timerange from overlapping ranges
while (true)
{
var x = except.FirstOrDefault(e => e.Start <= main.Start);
if (x != null)
{
if (x.End >= main.End)
{
return new List<TimeRange>();
}
main.Start = x.End;
except.Remove(x);
}
else
break;
}
while (true)
{
var x = except.FirstOrDefault(e => e.End >= main.End);
if (x != null)
{
main.End = x.Start;
except.Remove(x);
}
else
break;
}
if (!except.Any())
{
return new List<TimeRange> { main };
}
// 3. add range[start main to start of the 1. exception] to the list of valid ranges and shrink the main time range to start = end of the 1. exception and go through the procedure again
except.OrderBy(e => e.Start);
var valid = new List<TimeRange>{new TimeRange{Start = main.Start, End = except[0].Start}};
main.Start = except[0].End;
except.RemoveAt(0);
return valid.Union(GetFreeSlots(main, except)).ToList();
}
OK,你有什么已经尝试过? – MarcinJuraszek
第一次尝试就是在时间跨度上把所有这些“忽略跨度”都打翻,并从主要开始和结束跨度中减去它,但是这并没有考虑2个忽略跨度实际上与对方重叠的可能性(如例1) – JakeJ
第二次尝试是尝试将忽略日期对分组为非重叠对,因此在示例1中,对1和对2将变为03:00至09:00,然后变为04:00至09:00 if你包括主要的开始,但是我无法弄清楚在技术上如何去做(这个想法仍然在我的脑海中,想着它) – JakeJ