英文:
How do I solve this in Swift? - 600: Fatal error: Index out of range
问题
I am new to Swift and coding in general.
我是新手,对Swift和编码都不太了解。
I am trying to get a list of busy periods from multiple events that occur in one day but keep getting "index out of range."
我试图从一天内发生的多个事件中获取一个忙碌时间段的列表,但一直出现“索引超出范围”的错误。
What is wrong here? (I am sorry my code is very messy)
这里有什么问题?(对不起,我的代码很混乱)
func busyPeriod() -> [[String:Date]]{
var busylist: [[String: Date]] = []
var eventlist: [[String: Date]] =
[["start": 2023-02-16 09:00:00, "end": 2023-02-16 10:00:00],
["start": 2023-02-16 10:00:00, "end": 2023-02-16 10:15:00],
["start": 2023-02-16 13:00:00, "end": 2023-02-16 14:00:00]]
if eventlist.count == 1{
return eventlist
}
for i in eventlist.indices{
if i == 0 {
busylist += ["start": eventlist[0]["start"]!, "end": eventlist[0]["end"]!]]
} else {
//This part comes out as Thread 1: Fatal Error: Index out of range
if busylist[-1]["start"]! <= eventlist[i]["start"]!, eventlist[i]["start"]! <= busylist[-1]["end"]! {
busylist[-1]["start"] = min(busylist[-1]["start"]!, eventlist[i]["start"]!)
busylist[-1]["end"] = max(busylist[-1]["end"]!, eventlist[i]["end"]!)
} else {
busylist += ["start": eventlist[i]["start"]!, "end": eventlist[i]["end"]!]]
}}
return busylist
}
What I expect as an outcome:
我希望得到的结果如下:
busylist = [
["start": 2023-02-16 09:00:00, "end": 2023-02-16 10:15:00],
["start": 2023-02-16 13:00:00, "end": 2023-02-16 14:00:00]]
英文:
I am new to Swift and coding in general.
I am trying to get a list of busy periods from multiple events that occur in one day but keep getting "index out of range."
What is wrong here? (I am sorry my code is very messy)
`func busyPeriod() -> [[String:Date]]{
var busylist: [[String: Date]] = []
var eventlist: [[String: Date]] =
[["start": 2023-02-16 09:00:00, "end": 2023-02-16 10:00:00],
["start": 2023-02-16 10:00:00, "end": 2023-02-16 10:15:00]],
["start": 2023-02-16 13:00:00, "end": 2023-02-16 14:00:00]]
if eventlist.count == 1{
return eventlist
}
for i in eventlist.indices{
if i == 0 {
busylist += [["start": eventlist[0]["start"]!, "end": eventlist[0]["end"]!]]
} else {
//This part comes out as Thread 1: Fatal Error: Index out of range
if busylist[-1]["start"]! <= eventlist[i]["start"]!, eventlist[i]["start"]! <= busylist[-1]["end"]! {
busylist[-1]["start"] = min(busylist[-1]["start"]!, eventlist[i]["start"]!)
busylist[-1]["end"] = max(busylist[-1]["end"]!, eventlist[i]["end"]!)
} else {
busylist += [["start": eventlist[i]["start"]!, "end": eventlist[i]["end"]!]]
}}
return busylist
}
What I expect as an outcome:
busylist = [
["start": 2023-02-16 09:00:00, "end": 2023-02-16 10:15:00],
["start": 2023-02-16 13:00:00, "end": 2023-02-16 14:00:00]]
</details>
# 答案1
**得分**: 0
某些编程语言,例如Python,允许您使用负索引从数组的末尾开始计数。因此,在Python中,`busylist[-1]` 会给您数组 `busylist` 中的最后一个元素(如果 `busylist` 不为空)。
Swift 不支持这种行为。
此外,您的代码过于复杂,因为您使用了 `[String: Date]` 而不是一个特定领域的类型来存储时间跨度。
我会更像以下方式编写您的函数,尽管为了避免日期解析的复杂性,我只是使用 `String` 来保存日期(因此违反了我自己使用良好类型的建议😅):
```swift
import Foundation
struct TimeSpan: CustomStringConvertible {
var start: String
var end: String
var description: String {
"\(start) - \(end)"
}
}
func busyPeriods(for events: [TimeSpan]) -> [TimeSpan] {
guard var last = events.first else {
return []
}
var answer: [TimeSpan] = []
for event in events.dropFirst() {
if event.start <= last.end {
last.start = min(last.start, event.start)
last.end = max(last.end, event.end)
} else {
answer.append(last)
last = event
}
}
answer.append(last)
return answer
}
print(busyPeriods(for: [
.init(start: "2023-02-16 09:00:00", end: "2023-02-16 10:00:00"),
.init(start: "2023-02-16 10:00:00", end: "2023-02-16 10:15:00"),
.init(start: "2023-02-16 13:00:00", end: "2023-02-16 14:00:00"),
]))
输出:
[2023-02-16 09:00:00 - 2023-02-16 10:15:00, 2023-02-16 13:00:00 - 2023-02-16 14:00:00]
请注意,您的函数(以及我的重写)对输入做出了一些假设:
-
事件按照开始时间排序。
-
一个事件最多可以与一个之前的事件重叠。
如果违反了这些假设中的任何一个,函数将返回错误的答案。
英文:
Some languages, like Python, allow you to use a negative index to count back from the end of the array. So in Python, busylist[-1]
gives you the last element in the array busylist
(if busylist
is not empty).
Swift does not support that behavior.
Also, your code is needlessly complicated because you're using a [String: Date]
instead of a domain-specific type to store a time span.
I'd write your function more like the following, although to avoid the complication of date parsing, I'm just using String
to hold a date (thus violating my own advice to use good types 😅):
import Foundation
struct TimeSpan: CustomStringConvertible {
var start: String
var end: String
var description: String {
"\(start) - \(end)"
}
}
func busyPeriods(for events: [TimeSpan]) -> [TimeSpan] {
guard var last = events.first else {
return []
}
var answer: [TimeSpan] = []
for event in events.dropFirst() {
if event.start <= last.end {
last.start = min(last.start, event.start)
last.end = max(last.end, event.end)
} else {
answer.append(last)
last = event
}
}
answer.append(last)
return answer
}
print(busyPeriods(for: [
.init(start: "2023-02-16 09:00:00", end: "2023-02-16 10:00:00"),
.init(start: "2023-02-16 10:00:00", end: "2023-02-16 10:15:00"),
.init(start: "2023-02-16 13:00:00", end: "2023-02-16 14:00:00"),
]))
Output:
[2023-02-16 09:00:00 - 2023-02-16 10:15:00, 2023-02-16 13:00:00 - 2023-02-16 14:00:00]
Note that your function (and my rewrite) make some assumptions about the input:
-
The events are sorted by start time.
-
An event can only overlap at most one prior event.
If either of these assumptions is violated, the functions will return wrong answers.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论