【问题标题】:Comparing dates for overlap - not avoiding比较重叠日期 - 不避免
【发布时间】:2013-04-27 20:43:05
【问题描述】:

我正在编写一个时间表代码。我正在使用与这些模块相关的大学模块和事件系统,即

模块 CSC3039 Event1 - 讲座 Event2 - 讲座 Event3 - 实用等

我需要检查模块中每个事件的时间并比较冲突。冲突不需要纠正,只需突出显示即可。我将使用的表是Events,其中包含Event_ID (PK), Module_code (FK), Start_Date_Time, End_Date_Time 以及其他无关紧要的字段。我发现我需要实现一个For Each 语句,最终导致一个 if 语句,例如:

如果 (startTime1 = startTime2) CLASH

我的问题是试图在这里找出实际的 for 循环。我不知道该写什么来声明我的开始时间和结束时间。我认为这是获取 event1 并获取其开始和结束然后检查事件 2、3 或 4 是否符合上述 if 语句的情况。我正在努力解决这个问题,但确实可以使用一些指导。

编辑...根据以下建议,我实现了以下代码:

    'return all relevant tables from the Modules database, based on the module code entered by the user.
    Dim eventTime = (From mods In db.Modules
                    Join evnt In db.Events On mods.Module_code Equals evnt.Module_code
                    Join rm In db.Rooms On rm.Room_ID Equals evnt.Room_ID
                    Join build In db.Buildings On build.Building_code Equals rm.Building_code
                    Where ((mods.Module_code = initialModCode) And (evnt.Room_ID = rm.Room_ID))
                    Select evnt.Event_ID, evnt.Module_code, evnt.Event_type, evnt.Start_Date_Time, evnt.End_Date_Time, build.Building_code, rm.Room_Number)


    'use the gridview to display the result returned by the above query
    gdvEventsTable.DataSource = eventTime
    gdvEventsTable.DataBind()

    Dim listClashes As New List(Of Array)

    For i As Integer = 0 To eventTime.Count - 1
        For j As Integer = i + 1 To eventTime.Count - 1
            If (eventTime.ToList(i).Start_Date_Time < eventTime.ToList(j).End_Date_Time) And (eventTime.ToList(i).End_Date_Time > eventTime.ToList(j).Start_Date_Time) Then
                MsgBox("Clash", MsgBoxStyle.MsgBoxSetForeground, "")
                listClashes.Add(eventTime)
            Else
                MsgBox("No Clash", MsgBoxStyle.MsgBoxSetForeground, "")
            End If
        Next
    Next

在尝试将事件添加到我的数组列表时,我注意到在调试中没有事件发送到列表。

【问题讨论】:

  • 好的,现在这是 linq 特定的,我从未使用过 linq,所以我不知道这些东西。您需要以某种方式获取 eventTime 的第 i 个元素。在调试时将鼠标放在它上面,看看 eventTime 是什么类型的对象,然后用谷歌搜索它什么的。您还可以从 gridview 中获取所有信息,这可能会更容易。
  • 您可能应该使用包含/排除范围,而不是完全包含范围。请参阅 my answer 以了解最近发布的类似问题。

标签: vb.net linq datetime overlap


【解决方案1】:

如果要比较数组或某种集合中的所有事件对,可以使用如下循环:

    Dim ModuleEventArray() As ModuleEvent
    '...
    For i As Integer = 0 To ModuleEventArray.Length - 1
        For j As Integer = i + 1 To ModuleEventArray.Length - 1
            'test if ModuleEventArray(i) overlaps with ModuleEventArray(j)
        Next
    Next

此处的ModuleEvent 将是另一个具有字段startTime 和endTime 的类或结构。测试

if (startTime1 <= endTime2 or endTime1 >= startTime2)

不足以测试重叠,但也许你可以自己找出正确的测试:)


编辑: 因为我看到你使用某种集合,而不是数组,所以你需要的代码应该是这样的:

For i As Integer = 0 To eventTime.Count - 1
    For j As Integer = i + 1 To eventTime.Count - 1
        If (eventTime.Item(i).Start_Date_Time < eventTime.Item(j).End_Date_Time) And (eventTime.Item(i).End_Date_Time > eventTime.Item(j).Start_Date_Time) Then
            MsgBox("Clash")
        Else
            MsgBox("No Clash")
        End If
    Next
Next

【讨论】:

  • 感谢@Saulius Šimčikas 的简化。我很感激。该代码不起作用,因为它不喜欢 eventTime.Item 行。我将其更改为eventTime.ToList,这似乎有效,但我无法将冲突事件发送到我的数组列表。我已经更新了我的问题以显示我现在使用的代码。你能告诉我你对此的看法吗?提前致谢。
【解决方案2】:

在编写代码之前,您需要首先确定您的算法将是什么。例如,如果您使用假设的 naive 方法,代码确实很简单(基本上是 2 个嵌套循环),但复杂度为 O(n²)。

取决于您拥有的数据量、是否在数据库中、您期望发生冲突的可能性有多大、您是否总是在开始时拥有完整的事件列表,或者您需要逐步查找冲突等等...可能首选不同的解决方案。一个考虑因素是您是否需要将列表划分为不冲突的事件集,或者只生成一个是/否答案(每个事件一个)来说明是否存在冲突。

您可以考虑做一些不同的事情,例如在开始比较之前按开始时间对列表进行排序。这将允许您只在列表中走一次。

【讨论】:

  • 感谢您的意见@Celada。因为我是一个没有经验的编码员,所以这让我有点不知所措。数据在数据库中,不会包含大量数据。可以说是经常发生冲突。我不知道你说的 O(n2) 是什么意思
【解决方案3】:

我的比较来自数据库。在下面的代码之前,我有一个查询,它根据Module_Code 的用户输入返回我的Events 表中的所有记录。此代码将通过 msgbox 显示冲突。我将对其进行更改以填充列表。这不是最漂亮的,可能会导致很多重复,但它实现了我的主要目标。

For Each evnt In eventTime


        Dim startTime1 = evnt.Start_Date_Time

        Dim endTime1 = evnt.End_Date_Time

        For Each evat In eventTime
            Dim startTime2 = evat.Start_Date_Time


            Dim endTime2 = evat.End_Date_Time



            If (startTime1 < endTime2) And (endTime1 > startTime2) Then
                MsgBox("Clash")
            Else
                MsgBox("No Clash")
            End If

        Next

    Next

【讨论】:

  • 这段代码可以工作,但效果很差。您正在测试每一对两次,并且您正在针对自身测试每个事件,并且如果您需要它们,您应该在循环之外声明变量。
  • 嗨@SauliusŠimčikas 感谢您的评论。您能否提出一个更好的替代方案,即使是伪代码?如前所述,我是这方面的新手,我花了 6 个小时才走到这一步。
  • 我已经回答了。我刚刚对其进行了编辑,以便您更容易理解。
猜你喜欢
  • 1970-01-01
  • 2015-07-08
  • 1970-01-01
  • 1970-01-01
  • 2017-05-15
  • 2018-02-12
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多