gpt4 book ai didi

swift - 从 DateInterval 数组中排除 DateInterval 数组

转载 作者:搜寻专家 更新时间:2023-11-01 06:26:01 24 4
gpt4 key购买 nike

我想从 DateInterval 数组中排除 DateInterval 数组。这是我的代码,但我认为它不会有帮助。有时它会进入无限循环,我无法解决它。

extension DateInterval {

static func exclude(_ excludedIntervals: [DateInterval], from periods: [DateInterval]) -> [DateInterval] {
if excludedIntervals.isEmpty { return periods }
var resultSlots: [DateInterval] = []

for period in periods {
let results = period.exclude(excludedIntervals)
resultSlots.append(contentsOf: results)
}

return resultSlots
}

func exclude(_ execludedIntervals: [DateInterval]) -> [DateInterval] {
if execludedIntervals.isEmpty { return [self] }
var sortedExecludedIntervals = execludedIntervals.sorted()
var resultSlots: [DateInterval] = []
var execludedInterval = sortedExecludedIntervals.removeFirst()
// remove execludedIntervals from self
if let intersection = self.intersection(with: execludedInterval) {
if self.start == intersection.start && self.end > intersection.end {
let newSlot = DateInterval(start: intersection.end, end: self.end)
resultSlots.append(contentsOf: newSlot.exclude(sortedExecludedIntervals))
} else if self.start < intersection.start && self.end == intersection.end {
let newSlot = DateInterval(start: self.start, end: intersection.start)
resultSlots.append(contentsOf: newSlot.exclude(sortedExecludedIntervals))
} else if self.start < intersection.start && self.end > intersection.end {
let preSlot = DateInterval(start: self.start, end: intersection.start)
resultSlots.append(contentsOf: preSlot.exclude(sortedExecludedIntervals))
let postSlot = DateInterval(start: intersection.end, end: self.end)
resultSlots.append(contentsOf: postSlot.exclude(sortedExecludedIntervals))
} else {
// start = start && end = end
resultSlots = []
return resultSlots
}
}


return resultSlots
}
}

例如,我想从中午 12 点到下午 6 点的间隔中排除下午 1 点到下午 3 点和下午 5 点到下午 6 点的间隔。该函数应返回 12 pm - 1 pm 和 3 pm - 5 pm。

最佳答案

几个想法:

  1. 如果我想要一个方法对 DateInterval 数组进行操作,我建议将它放在 Array(或 Sequence code>) 扩展,限制为 DateInterval 类型,而不是 DateInterval 上的 static 方法:

    extension Array where Element == DateInterval {
    func exclude(_ excludedIntervals: [DateInterval]) -> [DateInterval] { ... }
    }
  2. 当考虑从另一个中排除一个 DateInterval 时,有很多不同的场景:

    • 您可以从间隔中间排除一些小窗口;
    • 您可以在间隔开始时排除一部分;
    • 您可以排除间隔末尾的一部分;和
    • 您可以排除整个区间。

    在我看来,考虑所有这些场景太困惑了,所以我决定稍微简化一下并决定:

    • 排除的区域与当前区间相交的确切位置(DateInterval 为我们提供了一个很好的方法);
    • 如果我从日期间隔中“剪掉”那个交集,我可能会得到两个间隔,一个before 间隔和一个after 间隔(例如,如果我剪掉中午 6 点到下午 2 点到下午 3 点,之前 时间间隔为中午到下午 2 点,之后 时间间隔为下午 3 点到 6 点);
    • 算法然后提炼为“如果区间与排除区域相交,则将原始区间替换为其他两个区间,一个在前,一个在后”;和
    • 考虑到我要改变结果间隔的原始数组,我建议使用嵌套循环,外循环是要排除的间隔,内循环是结果间隔,因为它在变化,所以我会使用 while 语句进行迭代,手动检查和调整当前的 index

产生:

extension Array where Element == DateInterval {
func exclude(_ excludedIntervals: [DateInterval]) -> [DateInterval] {
var results: [DateInterval] = self

for excludedInterval in excludedIntervals {
var index = results.startIndex
while index < results.endIndex {
let interval = results[index]
if let intersection = interval.intersection(with: excludedInterval) {
var before: DateInterval?
var after: DateInterval?

if intersection.start > interval.start {
before = DateInterval(start: interval.start, end: intersection.start)
}
if intersection.end < interval.end {
after = DateInterval(start: intersection.end, end: interval.end)
}
let replacements = [before, after].compactMap { $0 }
results.replaceSubrange(index...index, with: replacements)
index += replacements.count
} else {
index += 1
}
}
}

return results
}
}

然后我们可以将应用于单个 DateInterval 的排除视为仅包含一项的数组的特例:

extension DateInterval {
func exclude(_ excludedIntervals: [DateInterval]) -> [DateInterval] {
return [self].exclude(excludedIntervals)
}
}

所以:

let formatter = ISO8601DateFormatter()

let start = formatter.date(from: "2019-02-09T12:00:00Z")!
let end = formatter.date(from: "2019-02-09T18:00:00Z")!

let exclude1Start = formatter.date(from: "2019-02-09T13:00:00Z")!
let exclude1End = formatter.date(from: "2019-02-09T14:00:00Z")!

let exclude2Start = formatter.date(from: "2019-02-09T16:00:00Z")!
let exclude2End = formatter.date(from: "2019-02-09T17:00:00Z")!

let intervals = DateInterval(start: start, end: end)
.exclude([
DateInterval(start: exclude1Start, end: exclude1End),
DateInterval(start: exclude2Start, end: exclude2End)
])

print(intervals)

将产生:

[
2019-02-09 12:00:00 +0000 to 2019-02-09 13:00:00 +0000,
2019-02-09 14:00:00 +0000 to 2019-02-09 16:00:00 +0000,
2019-02-09 17:00:00 +0000 to 2019-02-09 18:00:00 +0000
]

关于swift - 从 DateInterval 数组中排除 DateInterval 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54612795/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com