在Swift中如何解决这个问题? – 600:致命错误:索引超出范围

huangapple go评论59阅读模式
英文:

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() -&gt; [[String:Date]]{

    var busylist: [[String: Date]] = []
    var eventlist: [[String: Date]] = 
      [[&quot;start&quot;: 2023-02-16 09:00:00, &quot;end&quot;: 2023-02-16 10:00:00], 
      [&quot;start&quot;: 2023-02-16 10:00:00, &quot;end&quot;: 2023-02-16 10:15:00]],
      [&quot;start&quot;: 2023-02-16 13:00:00, &quot;end&quot;: 2023-02-16 14:00:00]]

    if eventlist.count == 1{
       return eventlist
    }

    for i in eventlist.indices{
        if i == 0 {
            busylist += [[&quot;start&quot;: eventlist[0][&quot;start&quot;]!, &quot;end&quot;: eventlist[0][&quot;end&quot;]!]]
    } else {
        //This part comes out as Thread 1: Fatal Error: Index out of range
        if busylist[-1][&quot;start&quot;]! &lt;= eventlist[i][&quot;start&quot;]!, eventlist[i][&quot;start&quot;]! &lt;= busylist[-1][&quot;end&quot;]! { 
            busylist[-1][&quot;start&quot;] = min(busylist[-1][&quot;start&quot;]!, eventlist[i][&quot;start&quot;]!)
            busylist[-1][&quot;end&quot;] = max(busylist[-1][&quot;end&quot;]!, eventlist[i][&quot;end&quot;]!)
    } else {
        busylist += [[&quot;start&quot;: eventlist[i][&quot;start&quot;]!, &quot;end&quot;: eventlist[i][&quot;end&quot;]!]]
    }}
    return busylist
}

What I expect as an outcome:

    busylist = [
        [&quot;start&quot;: 2023-02-16 09:00:00, &quot;end&quot;: 2023-02-16 10:15:00],
        [&quot;start&quot;: 2023-02-16 13:00:00, &quot;end&quot;: 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 {
        &quot;\(start) - \(end)&quot;
    }
}

func busyPeriods(for events: [TimeSpan]) -&gt; [TimeSpan] {
    guard var last = events.first else {
        return []
    }
    
    var answer: [TimeSpan] = []
    
    for event in events.dropFirst() {
        if event.start &lt;= 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: &quot;2023-02-16 09:00:00&quot;, end: &quot;2023-02-16 10:00:00&quot;), 
    .init(start: &quot;2023-02-16 10:00:00&quot;, end: &quot;2023-02-16 10:15:00&quot;),
    .init(start: &quot;2023-02-16 13:00:00&quot;, end: &quot;2023-02-16 14:00:00&quot;),
]))

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.

huangapple
  • 本文由 发表于 2023年2月16日 17:14:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75470023.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定