C# 及时查找所有缺失的段
C# Find All Missing Segments In Time
我需要在 10 分钟内找到丢失的路段,我想知道最佳路线。
假设我有三个时间段。
- 2:30 - 3:43 分钟片段。
- 4:25 - 4:59 分钟片段。
- 7:21 - 9:55 分钟片段。
使用 C#,我有完整的 10:20 分钟时间段。当我已经有上面的 3 个片段时,我需要找到缺失的片段。
所以我需要用C#计算的段如下
- 0:00 - 2:29 分钟段。
- 3:44 - 4:24 分钟片段。
- 5:00 - 7:20 分钟段。
- 9:56 - 10:20 分钟片段。
那么我是从上面已知的 3 个细分中计算出这 4 个细分吗?
我认为我最好的方法是只做一个 for 循环并一直计算到 10:20 秒,然后检查当前秒数是否存在于 3 个分段中。如果不是,请将那一秒添加到缺失的部分。
我认为检查每一秒是否属于一个间隔不是一个好主意。我认为这个问题可以通过 O(n) complexity, of course using some .NET classes to structure the input that will make everything more easy. Full fiddle here.
来解决
private static List<Tuple<TimeSpan,TimeSpan>> ComputeMissingTimeSpans(List<Tuple<TimeSpan,TimeSpan>> availableIntervals, TimeSpan minSpan, TimeSpan maxSpan)
{
List<Tuple<TimeSpan,TimeSpan>> missingTime = new List<Tuple<TimeSpan,TimeSpan>>();
if(availableIntervals.Count == 0)
{
missingTime.Add(new Tuple<TimeSpan, TimeSpan>(minSpan, maxSpan));
return missingTime;
}
foreach(var interval in availableIntervals){
if((interval.Item1 - minSpan).TotalSeconds > 1 )
{
missingTime.Add(new Tuple<TimeSpan, TimeSpan>(minSpan, interval.Item1.Add(TimeSpan.FromSeconds(-1))));
}
minSpan = interval.Item2.Add(TimeSpan.FromSeconds(1));
}
if((maxSpan - minSpan).TotalSeconds > 1)
missingTime.Add(new Tuple<TimeSpan, TimeSpan>(minSpan, maxSpan));
return missingTime;
}
您可以根据需要轻松调整此功能。
按照@Matt Johnson 的绝妙想法,对于也适用于长 and/or 周期的更通用的解决方案,您可以创建一个 TimeSlot
结构:
public struct TimeSlot
{
private DateTime _start;
private TimeSpan _span;
public DateTime Start
{
get
{
if (_start == null)
{
_start = DateTime.Today;
}
return _start;
}
set
{
_start = value;
}
}
public TimeSpan Span
{
get
{
if (_span == null)
{
_span = new TimeSpan(0);
}
return _span;
}
set
{
if (value.Ticks >= 0)
{
_span = value;
}
}
}
public DateTime End
{
get
{
return Start.Add(Span);
}
}
public TimeSlot(DateTime start, TimeSpan span)
{
_start = start;
_span = span.Ticks >= 0 ? span : new TimeSpan(0);
}
}
然后您可以 运行 编写这样的代码,首先找到前导段,然后是中间的那些段,最后是尾随段:
public static void SlotDemo()
{
DateTime startTime = DateTime.Today;
DateTime endTime = startTime.Add(new TimeSpan(0, 10, 20));
List<TimeSlot> segments = new List<TimeSlot>();
segments.Add(new TimeSlot(startTime.Add(new TimeSpan(0, 2, 30)), new TimeSpan(0, 1, 13)));
segments.Add(new TimeSlot(startTime.Add(new TimeSpan(0, 4, 25)), new TimeSpan(0, 0, 35)));
segments.Add(new TimeSlot(startTime.Add(new TimeSpan(0, 7, 21)), new TimeSpan(0, 2, 34)));
for (int i = 0; i < segments.Count; i++)
{
Console.WriteLine("s: {0:mm':'ss} d: {1:mm':'ss} e: {2:mm':'ss}", segments[i].Start, segments[i].Span, segments[i].End);
}
Console.WriteLine();
if (!segments[0].Start.Equals(startTime))
{
TimeSlot firstSlot = new TimeSlot(startTime, segments[0].Start.Subtract(startTime));
segments.Insert(0, firstSlot);
}
for (int i = 0; i < segments.Count; i++)
{
Console.WriteLine("s: {0:mm':'ss} d: {1:mm':'ss} e: {2:mm':'ss}", segments[i].Start, segments[i].Span, segments[i].End);
}
Console.WriteLine();
for (int i = 0; i < segments.Count - 1; i++)
{
if (segments[i].End != segments[i + 1].Start)
{
TimeSlot slot = new TimeSlot(segments[i].End, segments[i + 1].Start.Subtract(segments[i].End));
segments.Insert(i + 1, slot);
i++;
}
}
for (int i = 0; i < segments.Count; i++)
{
Console.WriteLine("s: {0:mm':'ss} d: {1:mm':'ss} e: {2:mm':'ss}", segments[i].Start, segments[i].Span, segments[i].End);
}
Console.WriteLine();
int lastIndex = segments.Count - 1;
if (!segments[lastIndex].End.Equals(endTime))
{
TimeSlot lastSlot = new TimeSlot(segments[lastIndex].End, endTime.Subtract(segments[lastIndex].End));
segments.Add(lastSlot);
}
for (int i = 0; i < segments.Count; i++)
{
Console.WriteLine("s: {0:mm':'ss} d: {1:mm':'ss} e: {2:mm':'ss}", segments[i].Start, segments[i].Span, segments[i].End);
}
Console.ReadKey();
}
这将提供此输出:
s: 02:30 d: 01:13 e: 03:43
s: 04:25 d: 00:35 e: 05:00
s: 07:21 d: 02:34 e: 09:55
s: 00:00 d: 02:30 e: 02:30
s: 02:30 d: 01:13 e: 03:43
s: 04:25 d: 00:35 e: 05:00
s: 07:21 d: 02:34 e: 09:55
s: 00:00 d: 02:30 e: 02:30
s: 02:30 d: 01:13 e: 03:43
s: 03:43 d: 00:42 e: 04:25
s: 04:25 d: 00:35 e: 05:00
s: 05:00 d: 02:21 e: 07:21
s: 07:21 d: 02:34 e: 09:55
s: 00:00 d: 02:30 e: 02:30
s: 02:30 d: 01:13 e: 03:43
s: 03:43 d: 00:42 e: 04:25
s: 04:25 d: 00:35 e: 05:00
s: 05:00 d: 02:21 e: 07:21
s: 07:21 d: 02:34 e: 09:55
s: 09:55 d: 00:25 e: 10:20
我需要在 10 分钟内找到丢失的路段,我想知道最佳路线。
假设我有三个时间段。
- 2:30 - 3:43 分钟片段。
- 4:25 - 4:59 分钟片段。
- 7:21 - 9:55 分钟片段。
使用 C#,我有完整的 10:20 分钟时间段。当我已经有上面的 3 个片段时,我需要找到缺失的片段。
所以我需要用C#计算的段如下
- 0:00 - 2:29 分钟段。
- 3:44 - 4:24 分钟片段。
- 5:00 - 7:20 分钟段。
- 9:56 - 10:20 分钟片段。
那么我是从上面已知的 3 个细分中计算出这 4 个细分吗?
我认为我最好的方法是只做一个 for 循环并一直计算到 10:20 秒,然后检查当前秒数是否存在于 3 个分段中。如果不是,请将那一秒添加到缺失的部分。
我认为检查每一秒是否属于一个间隔不是一个好主意。我认为这个问题可以通过 O(n) complexity, of course using some .NET classes to structure the input that will make everything more easy. Full fiddle here.
来解决private static List<Tuple<TimeSpan,TimeSpan>> ComputeMissingTimeSpans(List<Tuple<TimeSpan,TimeSpan>> availableIntervals, TimeSpan minSpan, TimeSpan maxSpan)
{
List<Tuple<TimeSpan,TimeSpan>> missingTime = new List<Tuple<TimeSpan,TimeSpan>>();
if(availableIntervals.Count == 0)
{
missingTime.Add(new Tuple<TimeSpan, TimeSpan>(minSpan, maxSpan));
return missingTime;
}
foreach(var interval in availableIntervals){
if((interval.Item1 - minSpan).TotalSeconds > 1 )
{
missingTime.Add(new Tuple<TimeSpan, TimeSpan>(minSpan, interval.Item1.Add(TimeSpan.FromSeconds(-1))));
}
minSpan = interval.Item2.Add(TimeSpan.FromSeconds(1));
}
if((maxSpan - minSpan).TotalSeconds > 1)
missingTime.Add(new Tuple<TimeSpan, TimeSpan>(minSpan, maxSpan));
return missingTime;
}
您可以根据需要轻松调整此功能。
按照@Matt Johnson 的绝妙想法,对于也适用于长 and/or 周期的更通用的解决方案,您可以创建一个 TimeSlot
结构:
public struct TimeSlot
{
private DateTime _start;
private TimeSpan _span;
public DateTime Start
{
get
{
if (_start == null)
{
_start = DateTime.Today;
}
return _start;
}
set
{
_start = value;
}
}
public TimeSpan Span
{
get
{
if (_span == null)
{
_span = new TimeSpan(0);
}
return _span;
}
set
{
if (value.Ticks >= 0)
{
_span = value;
}
}
}
public DateTime End
{
get
{
return Start.Add(Span);
}
}
public TimeSlot(DateTime start, TimeSpan span)
{
_start = start;
_span = span.Ticks >= 0 ? span : new TimeSpan(0);
}
}
然后您可以 运行 编写这样的代码,首先找到前导段,然后是中间的那些段,最后是尾随段:
public static void SlotDemo()
{
DateTime startTime = DateTime.Today;
DateTime endTime = startTime.Add(new TimeSpan(0, 10, 20));
List<TimeSlot> segments = new List<TimeSlot>();
segments.Add(new TimeSlot(startTime.Add(new TimeSpan(0, 2, 30)), new TimeSpan(0, 1, 13)));
segments.Add(new TimeSlot(startTime.Add(new TimeSpan(0, 4, 25)), new TimeSpan(0, 0, 35)));
segments.Add(new TimeSlot(startTime.Add(new TimeSpan(0, 7, 21)), new TimeSpan(0, 2, 34)));
for (int i = 0; i < segments.Count; i++)
{
Console.WriteLine("s: {0:mm':'ss} d: {1:mm':'ss} e: {2:mm':'ss}", segments[i].Start, segments[i].Span, segments[i].End);
}
Console.WriteLine();
if (!segments[0].Start.Equals(startTime))
{
TimeSlot firstSlot = new TimeSlot(startTime, segments[0].Start.Subtract(startTime));
segments.Insert(0, firstSlot);
}
for (int i = 0; i < segments.Count; i++)
{
Console.WriteLine("s: {0:mm':'ss} d: {1:mm':'ss} e: {2:mm':'ss}", segments[i].Start, segments[i].Span, segments[i].End);
}
Console.WriteLine();
for (int i = 0; i < segments.Count - 1; i++)
{
if (segments[i].End != segments[i + 1].Start)
{
TimeSlot slot = new TimeSlot(segments[i].End, segments[i + 1].Start.Subtract(segments[i].End));
segments.Insert(i + 1, slot);
i++;
}
}
for (int i = 0; i < segments.Count; i++)
{
Console.WriteLine("s: {0:mm':'ss} d: {1:mm':'ss} e: {2:mm':'ss}", segments[i].Start, segments[i].Span, segments[i].End);
}
Console.WriteLine();
int lastIndex = segments.Count - 1;
if (!segments[lastIndex].End.Equals(endTime))
{
TimeSlot lastSlot = new TimeSlot(segments[lastIndex].End, endTime.Subtract(segments[lastIndex].End));
segments.Add(lastSlot);
}
for (int i = 0; i < segments.Count; i++)
{
Console.WriteLine("s: {0:mm':'ss} d: {1:mm':'ss} e: {2:mm':'ss}", segments[i].Start, segments[i].Span, segments[i].End);
}
Console.ReadKey();
}
这将提供此输出:
s: 02:30 d: 01:13 e: 03:43
s: 04:25 d: 00:35 e: 05:00
s: 07:21 d: 02:34 e: 09:55
s: 00:00 d: 02:30 e: 02:30
s: 02:30 d: 01:13 e: 03:43
s: 04:25 d: 00:35 e: 05:00
s: 07:21 d: 02:34 e: 09:55
s: 00:00 d: 02:30 e: 02:30
s: 02:30 d: 01:13 e: 03:43
s: 03:43 d: 00:42 e: 04:25
s: 04:25 d: 00:35 e: 05:00
s: 05:00 d: 02:21 e: 07:21
s: 07:21 d: 02:34 e: 09:55
s: 00:00 d: 02:30 e: 02:30
s: 02:30 d: 01:13 e: 03:43
s: 03:43 d: 00:42 e: 04:25
s: 04:25 d: 00:35 e: 05:00
s: 05:00 d: 02:21 e: 07:21
s: 07:21 d: 02:34 e: 09:55
s: 09:55 d: 00:25 e: 10:20