简体   繁体   English

如何比较数组中的时间?

[英]How can I compare times in an array?

I am building a bus arrival time application. 我正在构建公交车到达时间应用程序。 It needs a function to which two arguments are passed: a current stop which the user is at, and a destination stop which the user wants to go to. 它需要一个传递两个参数的函数:用户位于的当前停靠站,以及用户想要到达的目标停靠站。 The arrival times are hard-coded, and there are no "live arrival" times of any sort. 到达时间是硬编码的,并且没有任何“实时到达”时间。

The problem I am having is trying to compare the times and work out when the next bus is arriving. 我遇到的问题是尝试比较时间并确定下一辆公共汽车何时到达。 The times are stored in an array and cannot be changed. 时间存储在数组中,无法更改。

For example, if the array is as follows: ["08:00", "23:00", "01:00", "04:00"] and also, let us say the current time is "16:00", the time returned by the function is "23:00". 例如,如果数组如下:[“ 08:00”,“ 23:00”,“ 01:00”,“ 04:00”],并且也让我们说当前时间是“ 16:00” ,该函数返回的时间为“ 23:00”。 Simple, right? 简单吧? I have coded this bit already with an extension class which can be found in my Pastebin. 我已经使用扩展类对此位进行了编码,可以在我的Pastebin中找到它。

However, the problem arises when the time passes into "the next day", so if the time is "00:00", I don't know how to return "01:00", since my function will only return the first time in the array ("08:00") since "00:00" is lower than "08:00" . 但是,当时间进入“第二天”时会出现问题,因此,如果时间是“ 00:00”,我不知道如何返回“ 01:00”,因为我的函数只会返回第一次在数组(“ 08:00”)中,因为“ 00:00”低于“ 08:00”。

import UIKit

// Replace the variable currentTime with a value of "00:00" and see how my function returns "08:17" which is wrong. I want the function to return "00:03" since it is the next time in the array. Or if the current time is "01:00" it should return "01:03". BUT, if the current time is "01:04" or greater, it should return the first time in the array "08:17"

// Hard coded bus arrival times
let array: [String] = ["08:17", "08:37", "08:57", "09:21", "09:51", "10:21", "10:51", "11:21", "11:51", "12:21", "12:51", "13:21", "13:51", "14:21", "14:51", "15:21", "15:51", "16:21", "16:51", "17:21", "17:51", "18:21", "18:51", "19:21", "19:51", "21:03", "22:03", "23:03", "00:03", "01:03"]

// Date object stuff
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
let date = Date()
let calender = Calendar.current
let components = calender.dateComponents([.year, .month, .day, .hour, .minute, .second], from: date)
let year = components.year
let month = components.month
let day = components.day
let hour = components.hour
let minute = components.minute
let second = components.second

// Returns current time in a "HH:mm:ss" format
func getTimeString() -> String {
    var minuteAsString = String(minute!)

    if minute! < 10 {
        minuteAsString = "0\(String(minute!))"
    }

    let timeString = String(hour!) + ":" + minuteAsString
    return timeString
}

func getNextBus(_ currentStop: String,_ destinationStop: String) -> String {
    var listToUse: [String] = []
    let currentTime = getTimeString()
    print(currentTime)

    switch (currentStop, destinationStop) {
    case ("stop1", "stop2"):
        listToUse = array
    default: ()
    }
    print(listToUse)

    for busTime in listToUse {
        if currentTime < busTime {
            return busTime
        }
    }
    return "Error! No time found."
}

print(getNextBus("stop1", "stop2"))

// Time class which allows times to be compared and equated
class Time: Comparable, Equatable {
    init(_ date: Date) {
        //get the current calender
        let calendar = Calendar.current

        //get just the minute and the hour of the day passed to it
        let dateComponents = calendar.dateComponents([.hour, .minute], from: date)

        //calculate the seconds since the beggining of the day for comparisions
        let dateSeconds = dateComponents.hour! * 3600 + dateComponents.minute! * 60

        //set the varibles
        secondsSinceBeginningOfDay = dateSeconds
        hour = dateComponents.hour!
        minute = dateComponents.minute!
    }

    init(_ hour: Int, _ minute: Int) {
        //calculate the seconds since the beggining of the day for comparisions
        let dateSeconds = (hour * 3600 + minute * 60)

        //set the variables
        secondsSinceBeginningOfDay = dateSeconds
        self.hour = hour
        self.minute = minute
    }

    var hour : Int
    var minute: Int

    var date: Date {
        //get the current calender
        let calendar = Calendar.current

        //create a new date components.
        var dateComponents = DateComponents()

        dateComponents.hour = hour
        dateComponents.minute = minute

        return calendar.date(byAdding: dateComponents, to: Date())!
    }

    /// the number or seconds since the beginning of the day, this is used for comparisions
    public let secondsSinceBeginningOfDay: Int


    static func < (lhs: Time, rhs: Time) -> Bool {
        return lhs.secondsSinceBeginningOfDay < rhs.secondsSinceBeginningOfDay
    }

}```

Suppose we have this array: 假设我们有这个数组:

let array = ["08:00", "23:00", "01:00", "04:00"]

A more convenient way of dealing with "bus times" would be to define a struct like so: 处理“公交时间”的一种更方便的方法是定义一个结构,如下所示:

struct BusTime: Comparable, CustomStringConvertible {
    let hour    : Int
    let minute  : Int

    static func < (lhs: BusTime, rhs: BusTime) -> Bool {
        return (lhs.hour, lhs.minute) < (rhs.hour, rhs.minute)
    }

    var description: String {
        get {
            let formatter = NumberFormatter()
            formatter.minimumIntegerDigits = 2
            return formatter.string(for: hour)! + ":" + formatter.string(for: minute)!
        }
    }
}

NB: In the rest of the answer I'll be force-unwrapping for brevity) 注意:在剩下的答案中,为简洁起见,我将强制展开)

Let's create a sorted array of BusTime s: 让我们创建一个BusTime的排序数组:

let busTimes: [BusTime] = array.map { str in
    return BusTime(hour: Int(str.prefix(2))!, minute: Int(str.suffix(2))!)
}
var sortedBusTimes = busTimes.sorted()

Let's also define a variable nextBus which represents the next bus time: 我们还定义一个变量nextBus ,它代表下一个公交时间:

var nextBus: BusTime = sortedBusTimes[0]

Now, let's create a time that corresponds to say the current date: 现在,让我们创建一个与当前日期相对应的时间:

let nowComps = Calendar.current.dateComponents([.hour, .minute], from: Date())
let now = BusTime(hour: nowComps.hour!, minute: nowComps.minute!)

With binary search, we'll be able to find the next bus time in O(log(n)): 通过二进制搜索,我们将能够在O(log(n))中找到下一个公交车时间:

var low  = sortedBusTimes.startIndex
var high = sortedBusTimes.endIndex

while low < high {
    let middle = low + (high - low)/2      
    let middleTime = sortedBusTimes[middle]
    if middleTime == now {
        low = middle
        break
    } else if middleTime < now {
        low = middle + 1
    } else if now < middleTime {
        high = middle
    }
}

if low != sortedBusTimes.endIndex, high != 0 {
    nextBus = sortedBusTimes[low]
}

The definition middle could be simpler this way: middle的定义可以这样简单:

let middle = low + (high - low)/2

But take this article into consideration. 但是,采取这种文章考虑。

Finally, let's check: 最后,让我们检查一下:

print(nextBus)

At the time of writing this answer, it is 17:52. 在撰写此答案时,它是17:52。 So the result printed in the console is: 因此,在控制台中显示的结果是:

23:00

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM