Как отсортировать массив кортежей дат? - PullRequest
0 голосов
/ 27 ноября 2018

Используя Swift 4.2, я пытаюсь выяснить, как отсортировать мои объекты, содержащие две даты, так что самый последний объект находится первым в массиве.

list of objects in DB

Я экспериментирую со следующим, но это не удается из-за:

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

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 голосов
/ 28 ноября 2018

Кажется, сейчас это работает хорошо.Спасибо всем за помощь.100

// 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

0 голосов
/ 28 ноября 2018

Если ваш сервер и клиенты всегда будут находиться в одном часовом поясе (и вы не возражаете против падения времени перехода на летнее время), вы можете отсортировать объекты без преобразования строк в даты.

Если у вас есть большое количество объектов, будет более эффективно отобразить сортируемое значение, к которому применяется регулярная сортировка, а не выполнять преобразование даты 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)}
0 голосов
/ 27 ноября 2018

Я рекомендую

1 - использовать класс / структуру в качестве модели вместо кортежа

2 - Сделайте сервер и клиентские переменные как Date / timeStamp, которые вы заполняете, когда выполучить данные с помощью форматера

3 - сортировка по свойствам

. Для вашего текущего кода вам нужно

return lhs.$0! >= rhs.$0! && lhs.$1! >= rhs.$1!
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...