首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从DateInterval阵列中排除DateInterval阵列

从DateInterval阵列中排除DateInterval阵列
EN

Stack Overflow用户
提问于 2019-02-10 02:27:16
回答 1查看 199关注 0票数 1

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

代码语言:javascript
运行
复制
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 pm到6 pm的间隔中排除1 pm- 3 pm和5 pm-6 pm的间隔。该功能应返回下午12时至下午1时及下午3时至下午5时。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-02-10 04:23:48

有几个想法:

  1. 如果我想要一个方法对DateInterval数组进行操作,我建议将它放在Array (或Sequence)扩展中,限制为DateInterval类型,而不是DateInterval上的static方法: 扩展数组,其中元素== DateInterval { func排除(_ excludedIntervals: DateInterval) -> DateInterval {.}
  2. 当考虑从另一个场景中排除DateInterval时,有大量不同的场景:
代码语言:javascript
运行
复制
- You could exclude some small window from the middle of the interval;
- You could exclude a portion at the start of the interval;
- You could exclude a portion at the end of the interval; and
- You could exclude the whole interval.

在我看来,考虑所有这些场景都会变得过于混乱,所以我决定简化一下,并决定:

代码语言:javascript
运行
复制
- Where exactly does the excluded region intersect with the current interval (and `DateInterval` supplies a nice method to do that for us);
- If I “cut out” that intersection from the date interval, I might end up with two intervals, a `before` interval and an `after` interval (e.g. if I cut 2pm-3pm out of noon-6pm, the `before` interval will be noon-2pm and the `after` interval will be 3pm-6pm);
- The algorithm then distills down to “if the interval is intersected by the excluded region, replace the original interval with the two other intervals, the one before and the one after”; and
- Given that I’m mutating the original array of resulting intervals, I’d suggest nested loops, with the outer loop being the intervals to be excluded and the inner loop being the resulting intervals which, because it’s mutating, I’ll iterate through using a `while` statement, manually checking and adjusting the current `index`.

这会产生:

代码语言:javascript
运行
复制
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的排除作为数组中一个项的特殊情况来考虑:

代码语言:javascript
运行
复制
extension DateInterval {
    func exclude(_ excludedIntervals: [DateInterval]) -> [DateInterval] {
        return [self].exclude(excludedIntervals)
    }
}

所以:

代码语言:javascript
运行
复制
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)

将产生:

代码语言:javascript
运行
复制
[
    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
] 
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54612795

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档