使用 Elixir 过滤重叠的时间段

Filter overlapping time periods using Elixir

我有两个包含开始时间和结束时间的元组列表。所有开始和结束时间都是 Time 结构。

我想过滤掉与 booked_slots:

重叠的 time_slots
time_slots = [
  {~T[09:00:00], ~T[17:00:00]},
  {~T[13:00:00], ~T[17:00:00]},
  {~T[13:00:00], ~T[21:00:00]},
  {~T[17:00:00], ~T[21:00:00]},
  {~T[09:00:00], ~T[13:00:00]},
  {~T[09:00:00], ~T[21:00:00]}
]

booked_slots = [{~T[14:00:00], ~T[21:00:00]}]

应该留给我们的是:

[
  {~T[09:00:00], ~T[13:00:00]}
]

我尝试了以下方法(改编自对先前相关问题的回答:):

Enum.filter(time_slots, fn {time_start, time_end} ->
  Enum.any?(booked_slots, fn {booking_start, booking_end} ->
    if Time.compare(booking_start, time_start) == :lt do
      Time.compare(booking_end, time_start) == :gt
    else
      Time.compare(booking_start, time_end) == :lt
    end
  end)
end)

但是这个 returns:

[
  {~T[09:00:00], ~T[17:00:00]},
  {~T[13:00:00], ~T[17:00:00]},
  {~T[13:00:00], ~T[21:00:00]},
  {~T[17:00:00], ~T[21:00:00]},
  {~T[09:00:00], ~T[21:00:00]}
]

我们还需要考虑可能相等但不重叠的时间。例如:

time_slots = [
  {~T[09:00:00], ~T[17:00:00]},
  {~T[13:00:00], ~T[17:00:00]},
  {~T[13:00:00], ~T[21:00:00]},
  {~T[17:00:00], ~T[21:00:00]},
  {~T[09:00:00], ~T[21:00:00]},
  {~T[09:00:00], ~T[13:00:00]}
]

booked_slots = [{~T[17:00:00], ~T[21:00:00]}]

应该return…

[
  {~T[09:00:00], ~T[17:00:00]},
  {~T[13:00:00], ~T[17:00:00]},
  {~T[09:00:00], ~T[13:00:00]}
]

您需要过滤掉所有在预订时段内有开始或结束时间的时段。

Enum.reject(time_slots, fn {ts, te} ->
  Enum.any?(booked_slots, fn {bs, be} ->
    (Time.compare(ts, bs) != :lt and Time.compare(ts, be) == :lt) or
    (Time.compare(te, bs) == :gt and Time.compare(te, be) != :gt) or
    (Time.compare(ts, bs) == :lt and Time.compare(te, be) == :gt)
  end)
end)

第一个条件检查开始时间在预订时段内的时段,第二个条件检查结束时间在预订时段内的时段,第三个条件检查包含整个预订时段的时段。