如何排序日期元组的数组?

时间:2018-11-27 20:44:52

标签: swift sorting date tuples

使用Swift 4.2,我试图找出对包含两个日期的对象进行排序的方法,以便最近的对象在数组中排在第一位。

list of objects in DB

我正在尝试以下操作,但由于以下原因而失败:

Binary operator '>=' cannot be applied to two '(Date?, Date?)' operands

let sortedSignComments = signComments.sorted(by: {
    guard let serverDate0 = $0.serverLastUpdated else { return false }
    guard let serverDate1 = $1.serverLastUpdated else { return false }

    guard let clientDate0 = $0.clientLastUpdated else { return false }
    guard let clientDate1 = $1.clientLastUpdated else { return false }

    let lhs = (formatter.date(from: serverDate0), formatter.date(from: clientDate0))
    let rhs = (formatter.date(from: serverDate1), formatter.date(from: clientDate1))

    return lhs >= rhs
})

3 个答案:

答案 0 :(得分:0)

我推荐

1-将class / struct用作模型而不是元组

2-将服务器&&客户端变量设为Date / timeStamp,当您使用格式化程序获取数据时将其填充

3-根据属性排序

您需要当前代码

return lhs.$0! >= rhs.$0! && lhs.$1! >= rhs.$1!

答案 1 :(得分:0)

现在看来效果很好。谢谢大家的帮助。

// fyi ref: @Martin R, https://stackoverflow.com/a/53427282/7599
func filterOptionalsWithLargeNil<T: Comparable>(lhs: T?, rhs: T?) -> T? {
    var result: T?

    switch (lhs, rhs) {
    case let(l?, r?): result = l > r ? l : r    // Both lhs and rhs are not nil
    case let(nil, r?): result = r               // Lhs is nil
    case let(l?, nil): result = l               // Lhs is not nil, rhs is nil
    case (.none, .none):
        result = nil
    }

    return result
}

...

    let formatter = DateFormatter()
    formatter.locale = Locale(identifier: "en_US_POSIX")
    formatter.timeZone = TimeZone.autoupdatingCurrent
    formatter.dateFormat = DALconfig.ISO8601dateFormat

    let sortedSignComments = signComments.sorted(by: {
        // Convert ISO8601 date string format to Date() object.
        let serverDate0: Date? = $0.serverLastUpdated != nil ? formatter.date(from: $0.serverLastUpdated!) : nil
        let serverDate1: Date? = $1.serverLastUpdated != nil ? formatter.date(from: $1.serverLastUpdated!) : nil
        let clientDate0: Date? = $0.clientLastUpdated != nil ? formatter.date(from: $0.clientLastUpdated!) : nil
        let clientDate1: Date? = $1.clientLastUpdated != nil ? formatter.date(from: $1.clientLastUpdated!) : nil

        // Filter and sort each object separately.
        let objDate0: Date? = self.filterOptionalsWithLargeNil(lhs: serverDate0, rhs: clientDate0)
        let objDate1: Date? = self.filterOptionalsWithLargeNil(lhs: serverDate1, rhs: clientDate1)

        // Final comparison.
        guard let finalDate0 = objDate0 else { return false }
        guard let finalDate1 = objDate1 else { return false }

        return finalDate0.compare(finalDate1) == .orderedDescending

    })

结果:

enter image description here

答案 2 :(得分:0)

如果服务器和客户端始终处于同一时区(并且您不介意秋季夏令时),则可以对对象进行排序,而无需将字符串转换为日期。

如果对象数量很多,映射到可应用常规排序的可排序值将比映射N * Log(N)次更有效。

例如:

func getSortKey(obj:MyObject) -> Date { return .... }
sortedObjects = objectList.map{($0,getSortKey($0))}.sorted{$0.1>$1.1}.map{$0.0}

对于您的特定要求,getSortKey()函数可能需要从对象中选择两个日期之一,以便只有一个要比较的值。我猜您会希望按两个日期中的最新日期对对象进行排序,以便函数可以返回类似以下内容(伪代码):

 var sortKey = Date.distantPast 
 if let serverDateString = obj.serverLastUpdated,
    let serverDate       = formatter.date(from: serverDateString)
 { sortKey = serverDate }
 if let clientDateString = obj.clientLastUpdated,
    let clientDate       = formatter.date(from: clientDateString),
    sortKey < clientDate
 { sortKey = clientDate }
 return  sortKey

如果您没有大量对象,则可以直接在排序中使用该函数:

sortedObjects = objectList.sorted{getSortKey($0)>getSortKey($1)}