TimeSpan 中一天的非活动间隔
Inactive Interval of a day in TimeSpan
我有一个名为 Slot
的 c# class,它的所有 TimeSpan
属性只接受从 0:00:00
到 1.00:00:00
的值。
public class Slot
{
public TimeSpan StartTime { get; set; }
public TimeSpan EndTime { get; set; }
}
我将这些值作为我的活动间隔,它们彼此不重叠:
var activeIntervals= new List<Slot>
{
new Slot
{
StartTime = new TimeSpan(10,0,0),
EndTime = new TimeSpan(12,0,0),
},
new Slot
{
StartTime = new TimeSpan(12,0,0),
EndTime = new TimeSpan(13,0,0),
},
new Slot
{
StartTime = new TimeSpan(16,0,0),
EndTime = new TimeSpan(22,0,0),
}
};
是否有任何逻辑可以将一天中的其他时间间隔作为 inactiveIntervals?
在这种情况下,我想要这样的结果:
0:00:00
到 10:00:00
、13:00:00
到 16:00:00
和 22:00:00
到 1.00:00:00
试试下面的逻辑。它会为你工作。
你可以test it here
var activeIntervals = new List<Slot>
{
new Slot
{
StartTime = new TimeSpan(10,0,0),
EndTime = new TimeSpan(12,0,0),
},
new Slot
{
StartTime = new TimeSpan(12,0,0),
EndTime = new TimeSpan(13,0,0),
},
new Slot
{
StartTime = new TimeSpan(16,0,0),
EndTime = new TimeSpan(22,0,0),
}
};
activeIntervals = activeIntervals.OrderBy(x => x.StartTime).ToList();
var inActiveIntervals = new List<Slot>();
TimeSpan start = new TimeSpan(0,0,0);
TimeSpan end = new TimeSpan(24,0,0);
for (int i = 0; i < activeIntervals.Count(); i++)
{
if (start < activeIntervals[i].StartTime)
{
inActiveIntervals.Add(new Slot { StartTime = start, EndTime = activeIntervals[i].StartTime });
}
start = activeIntervals[i].EndTime;
}
if (start < end)
{
inActiveIntervals.Add(new Slot { StartTime = start, EndTime = end });
start = end;
}
for (int i = 0; i < inActiveIntervals.Count(); i++)
{
Console.WriteLine(inActiveIntervals[i].StartTime.ToString() + " - " + inActiveIntervals[i].EndTime.ToString());
}
一个关于 linq 的想法:
var inactiveIntervals = activeIntervals
.Zip(activeIntervals.Skip(1), (first, second) => {
if (second.StartTime - first.EndTime != TimeSpan.Zero) // Get rid of regions that don't have 'gap', e.g. 12:00:00 to 12:00:00
return new Slot { StartTime = first.EndTime, EndTime = second.StartTime };
return null;
}).Where(a => a != null).ToList(); // Filter out nulls
// Insert range from start to first date
inactiveIntervals.Insert(0, new Slot { StartTime = TimeSpan.Zero, EndTime = activeIntervals[0].StartTime });
// Insert range from last date to end
inactiveIntervals.Add(new Slot { StartTime = activeIntervals.Last().EndTime, EndTime = new TimeSpan(1, 0, 0, 0) });
这使用了 .Zip
的技巧,您可以在其中获取一个列表,然后将其与移动 1 的相同列表压缩。然后您可以将一个元素的 EndTime
与 StartTime
进行比较来自下一个元素。
没有间隙的过滤区域有点丑陋。你必须检查边缘情况。
您需要创建 List<Slot>
的新实例,然后使用列表元素的迭代添加 activeIntervals
列表中不存在的日期间隔。
public static class SlotExtensions
{
public static List<Slot> GetInactive(this List<Slot> slots)
{
Slot day = new Slot
{
StartTime = new TimeSpan(0,0,0),
EndTime = new TimeSpan(24,0,0)
}
List<Slot> inactive = new List<Slot>();
Slot tmp;
foreach(Slot slot in slots)
{
if(day.StartTime < slot.StartTime)
{
tmp = new Slot
{
StartTime = day.StartTime;
EndTime = slot.StartTime;
};
inactive.Add(tmp);
};
day.StartTime = slot.EndTime;
}
if(day.StartTime < day.EndTime)
{
inactive.Add(day);
}
return inactive;
}
}
扩展方法使用 day
,即 Slot
class 的实例,适合全天。然后我们将 day
和迭代槽的开始之间的差异添加到新列表,然后将 day
的开始移动到迭代槽的末尾。当循环结束时,方法将剩余间隔添加到列表中。
我有一个名为 Slot
的 c# class,它的所有 TimeSpan
属性只接受从 0:00:00
到 1.00:00:00
的值。
public class Slot
{
public TimeSpan StartTime { get; set; }
public TimeSpan EndTime { get; set; }
}
我将这些值作为我的活动间隔,它们彼此不重叠:
var activeIntervals= new List<Slot>
{
new Slot
{
StartTime = new TimeSpan(10,0,0),
EndTime = new TimeSpan(12,0,0),
},
new Slot
{
StartTime = new TimeSpan(12,0,0),
EndTime = new TimeSpan(13,0,0),
},
new Slot
{
StartTime = new TimeSpan(16,0,0),
EndTime = new TimeSpan(22,0,0),
}
};
是否有任何逻辑可以将一天中的其他时间间隔作为 inactiveIntervals?
在这种情况下,我想要这样的结果:
0:00:00
到 10:00:00
、13:00:00
到 16:00:00
和 22:00:00
到 1.00:00:00
试试下面的逻辑。它会为你工作。
你可以test it here
var activeIntervals = new List<Slot>
{
new Slot
{
StartTime = new TimeSpan(10,0,0),
EndTime = new TimeSpan(12,0,0),
},
new Slot
{
StartTime = new TimeSpan(12,0,0),
EndTime = new TimeSpan(13,0,0),
},
new Slot
{
StartTime = new TimeSpan(16,0,0),
EndTime = new TimeSpan(22,0,0),
}
};
activeIntervals = activeIntervals.OrderBy(x => x.StartTime).ToList();
var inActiveIntervals = new List<Slot>();
TimeSpan start = new TimeSpan(0,0,0);
TimeSpan end = new TimeSpan(24,0,0);
for (int i = 0; i < activeIntervals.Count(); i++)
{
if (start < activeIntervals[i].StartTime)
{
inActiveIntervals.Add(new Slot { StartTime = start, EndTime = activeIntervals[i].StartTime });
}
start = activeIntervals[i].EndTime;
}
if (start < end)
{
inActiveIntervals.Add(new Slot { StartTime = start, EndTime = end });
start = end;
}
for (int i = 0; i < inActiveIntervals.Count(); i++)
{
Console.WriteLine(inActiveIntervals[i].StartTime.ToString() + " - " + inActiveIntervals[i].EndTime.ToString());
}
一个关于 linq 的想法:
var inactiveIntervals = activeIntervals
.Zip(activeIntervals.Skip(1), (first, second) => {
if (second.StartTime - first.EndTime != TimeSpan.Zero) // Get rid of regions that don't have 'gap', e.g. 12:00:00 to 12:00:00
return new Slot { StartTime = first.EndTime, EndTime = second.StartTime };
return null;
}).Where(a => a != null).ToList(); // Filter out nulls
// Insert range from start to first date
inactiveIntervals.Insert(0, new Slot { StartTime = TimeSpan.Zero, EndTime = activeIntervals[0].StartTime });
// Insert range from last date to end
inactiveIntervals.Add(new Slot { StartTime = activeIntervals.Last().EndTime, EndTime = new TimeSpan(1, 0, 0, 0) });
这使用了 .Zip
的技巧,您可以在其中获取一个列表,然后将其与移动 1 的相同列表压缩。然后您可以将一个元素的 EndTime
与 StartTime
进行比较来自下一个元素。
没有间隙的过滤区域有点丑陋。你必须检查边缘情况。
您需要创建 List<Slot>
的新实例,然后使用列表元素的迭代添加 activeIntervals
列表中不存在的日期间隔。
public static class SlotExtensions
{
public static List<Slot> GetInactive(this List<Slot> slots)
{
Slot day = new Slot
{
StartTime = new TimeSpan(0,0,0),
EndTime = new TimeSpan(24,0,0)
}
List<Slot> inactive = new List<Slot>();
Slot tmp;
foreach(Slot slot in slots)
{
if(day.StartTime < slot.StartTime)
{
tmp = new Slot
{
StartTime = day.StartTime;
EndTime = slot.StartTime;
};
inactive.Add(tmp);
};
day.StartTime = slot.EndTime;
}
if(day.StartTime < day.EndTime)
{
inactive.Add(day);
}
return inactive;
}
}
扩展方法使用 day
,即 Slot
class 的实例,适合全天。然后我们将 day
和迭代槽的开始之间的差异添加到新列表,然后将 day
的开始移动到迭代槽的末尾。当循环结束时,方法将剩余间隔添加到列表中。