在我的iOS应用中,我有一个事件列表,每个事件都有开始和结束日期。我的目标是弄清楚哪些事件相互重叠-意思是,如果event1在10月6日星期一2:30 pm开始并在5:30 pm结束,而event4在10月6日星期一3:30 pm 3点开始了。我需要知道这两个事件是重叠的。
因此,当从网络上下载数据时,我创建了一个[DateInterval]
数组,分别具有每个EventObjects
的开始日期和结束日期。
我的问题是,迭代eventObjects数组然后检查开始日期是否与[DateInterval]
日期相交的最佳方法是什么?
提前谢谢
编辑
这是示例代码。
func sortArray (){
for object in sortedEventObjectArray {
let hasConflics = zip(datesReversed, datesReversed.dropFirst()).contains(where: { $0.end > $1.start })
if hasConflics == true {
print("conflict")
} else {
print("none")
}
}
}
[sortedEventObjectArray] is an event object which contains details like the start date and end date of event - this is what i used to populate the datesReserved array of Date Intervals
[datesReversed] is an array of DateIntervals - it looks like this
[2018-11-01 06:00:00 +0000 to 2018-11-01 09:30:00 +0000, 2018-11-01 18:00:00 +0000 to 2018-11-01 19:33:00 +0000, 2018-11-01 19:33:00 +0000 to 2018-11-01 23:00:00 +0000, 2018-11-03 18:14:00 +0000 to 2018-11-03 21:44:00 +0000, 2018-11-03 18:14:00 +0000 to 2018-11-03 21:44:00 +0000, 2018-11-06 12:00:00 +0000 to 2018-11-06 13:26:00 +0000, 2018-11-06 13:27:00 +0000 to 2018-11-06 14:00:00 +0000, 2018-11-06 17:00:00 +0000 to 2018-11-06 22:00:00 +0000, 2018-11-06 18:00:00 +0000 to 2018-11-06 21:00:00 +0000, 2018-11-07 12:00:00 +0000 to 2018-11-07 14:30:00 +0000, 2018-11-07 18:30:00 +0000 to 2018-11-07 23:00:00 +0000, 2018-11-08 11:30:00 +0000 to 2018-11-08 12:59:00 +0000, 2018-11-08 12:56:00 +0000 to 2018-11-08 13:30:00 +0000, 2018-11-08 19:30:00 +0000 to 2018-11-08 22:30:00 +0000, 2018-11-09 12:30:00 +0000 to 2018-11-09 14:30:00 +0000, 2018-11-09 15:00:00 +0000 to 2018-11-09 16:00:00 +0000, 2018-11-09 16:30:00 +0000 to 2018-11-09 21:00:00 +0000, 2018-11-09 20:00:00 +0000 to 2018-11-09 21:30:00 +0000, 2018-11-10 12:30:00 +0000 to 2018-11-10 20:30:00 +0000, 2018-11-10 13:45:00 +0000 to 2018-11-10 14:30:00 +0000, 2018-11-10 18:00:00 +0000 to 2018-11-10 19:00:00 +0000]
我得到的输出是-(这是错误的,因为很明显这些日期中的一些没有计划冲突)
conflict
conflict
conflict
conflict
conflict
conflict
conflict
conflict
conflict
conflict
conflict
conflict
conflict
conflict
conflict
conflict
conflict
conflict
答案 0 :(得分:1)
一种有效的解决方案是通过先增加开始日期来排序事件。然后,您只需将每个事件与稍后开始的事件进行比较。
如果模型对象是
struct Event {
let title: String
let duration: DateInterval
}
然后它可能看起来像这样(未经测试):
var events: [Event] = ...
events.sort(by: { $0.duration.start < $1.duration.start })
for i in events.indices.dropLast() {
for j in (i + 1)..<events.endIndex {
if events[i].duration.end > events[j].duration.start {
print(events[i].title, "overlaps with", events[j].title)
} else {
break
}
}
}
请注意,如果找到了不重叠的事件,则内循环可以终止,因为这些事件按开始日期的增加进行排序。
如果您只需要知道任何事件是否重叠,则可以将每个事件的持续时间与以下事件的持续时间进行比较:
var events: [Event] = ...
events.sort(by: { $0.duration.start < $1.duration.start })
var hasConflicts = false
for i in events.indices.dropLast() {
if events[i].duration.end > events[i+1].duration.start {
hasConflics = true
break
}
}
使用zip
可以将该代码缩写为
var events: [Event] = ...
events.sort(by: { $0.duration.start < $1.duration.start })
let hasConflics = zip(events, events.dropFirst())
.contains(where: { $0.duration.end > $1.duration.start })
答案 1 :(得分:0)
您可以扩展DateInterval
来检查重叠事件。
我们可以将其细分为3个验证以进行检查: (假设事件eventA已经设置,并且您要针对它检查eventB)
鉴于此,我认为此解决方案可以完成工作:
extension DateInterval {
func isOverlaps(with di: DateInterval) -> Bool {
let answer =
checkIfDItartAtTheSameTime(dateInterval: di) ||
checkIfDIIsBetween(date: di.start) ||
checkIfDIIsBetween(date: di.end) ||
checkIfDIStartsBeforeAndEndsAfter(dateInterval: di)
return answer
}
private func checkIfDIIsBetween(date: Date) -> Bool {
return date > start && date < end || date == start
}
private func checkIfDIStartsBeforeAndEndsAfter(dateInterval: DateInterval) -> Bool {
return dateInterval.start < start && dateInterval.end > end
}
private func checkIfDItartAtTheSameTime(dateInterval: DateInterval) -> Bool {
return dateInterval.start == start
}
}
现在,在迭代中,您只需检查:
[intervalA, intervalB].forEach { di in
if di.isOverlaps(with: someOtherDateInterval) {
print("conflict")
} else {
print("Not Conflicting!")
}
}
希望有帮助! :)