合并时隙的最简单算法

easiest algorithm to merge time slots

下图试图表示时隙列表。最后一行代表合并结果。 每个槽由 start/end(日期和时间)和类型 (green/yellow) 组成。 最终的结果需要return一些规则的合并插槽,其中如果有绿色与黄色重叠,则绿色为准。

我目前的方法是从按时间排序的列表开始。 但此刻我的代码变得混乱,不知何故使用递归逻辑....我不确定这是否是最简单的方法。

如果“时隙”的大小在某种程度上是独一无二的,那将很容易,但情况并非如此,因为我正在处理 minutes/seconds...并且“重叠”可以与如此小的时间段相吻合单位。

我不是要解决方案代码,而是要一些帮助,指出一些用于此类问题的已知算法。我可以阅读的一些网页网址等。 谢谢。

如果您使用排序列表,解决方案非常简单。

在开始时间和结束时间中拆分每个间隔,每个间隔带有 +1 和 -1 标签。如果您需要根据颜色实现额外的逻辑,请将该信息集成到标签中。

现在对所有时间进行递增排序(如果列表最初已排序,则使用完整排序或合并)。通过增加处理时间,您将保持正在进行的任务数。他们的联合对应于一个非零数。您可以根据“彩色”数字实施您想要的任何规则。

我想我找到了一个乍看起来很简单的解决方案。 我仍然需要用其他一些样本对其进行测试...但我相信如果仍然存在任何错误,解决方案不会增加其复杂性。

无论如何,请随时帮助我改进它。 谢谢

/***************************************************************************/
var processDateTime = filter.From;
var continueLoop = true;                    
while (continueLoop)
{
    var target = mergedMachineSlotsOfTimeRaw.Where(x => x.From >= processDateTime)
                                            .OrderBy(x => x.From).FirstOrDefault();
    if (target == null)
    {
        continueLoop = false;
    }
    else
    {
        mergedMachineSlotsOfTimeRaw = GetMergedSlot(target, mergedMachineSlotsOfTimeRaw);
        processDateTime = target.To.Value;
    }
}                                                                
/***************************************************************************/

其他功能

private List<DTOTempMachineSlot> GetMergedSlot(DTOTempMachineSlot original,
                                       List<DTOTempMachineSlot> originalList)
{
    var overlappedEntries = originalList.Where(x => x.Id != original.Id
                                                    && x.From >= original.From
                                                    && x.From < original.To);
    if (overlappedEntries.Count() == 0)
    {
        return originalList;
    }
    var newFinalList = new List<DTOTempMachineSlot>();
    var longestEntry = overlappedEntries.OrderByDescending(x => x.To).FirstOrDefault();

    var deleteLongestEntry = false;
    if (original.State == longestEntry.State)
    {
        if(original.To < longestEntry.To) {
                  original.To = longestEntry.To;
        }
        deleteLongestEntry = true;
    }
    else if (original.State == "S" && longestEntry.State == "E")
    {
        original.To = original.To;
        longestEntry.From = original.To.Value;
    }
    else if (original.State == "E" && longestEntry.State == "S")
    {
        original.To = longestEntry.To;
    }

    newFinalList.Add(original);
    if (deleteLongestEntry == false)
    {
        newFinalList.Add(longestEntry);
    }
    newFinalList.AddRange(originalList.Where(x => x.Id != original.Id 
                    && overlappedEntries.Any(y=>y.Id == x.Id) == false));

    return newFinalList;
}