Сортировать ноль до конца массива необязательных строк - PullRequest
0 голосов
/ 22 ноября 2018

Если у меня есть массив необязательных строк, и я хочу отсортировать его в порядке возрастания с нулями в начале, я могу легко сделать это в одной строке:

["b", nil, "a"].sorted{ $0 ?? "" < $1 ?? "" } // [nil, "a", "b"]

Но это не такПохоже, такое же простое решение для сортировки nils на end массива.Это можно легко сделать с большинством других простых типов данных, например:

[2, nil, 1].sorted{ $0 ?? Int.max < $1 ?? Int.max } // [1, 2, nil]

Для двойников вы можете сделать то же самое с greatestFiniteMagnitude, для дат вы можете использовать distantFuture.Есть ли какой-нибудь эквивалент для строк или какой-либо другой лаконичный способ сделать это, чтобы я мог не написать кучу беспорядочных условных выражений?

Ответы [ 3 ]

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

Ваш пример с Int дает подсказку.Если бы у нас было максимальное строковое значение, мы могли бы подключить его.

Это работает для строк, которые содержат только буквенные символы:

let maxString = "~"
["b", nil, "a"].sorted{ $0 ?? maxString < $1 ?? maxString }

Или просто:

["b", nil, "a"].sorted{ $0 ?? "~" < $1 ?? "~" }
0 голосов
/ 22 ноября 2018

Вы можете предоставить пользовательский компаратор, который считает nil большим, чем любое ненулевое значение:

let array = ["b", nil, "a", nil]

let sortedArray = array.sorted { (lhs, rhs) -> Bool in
    switch (lhs, rhs) {
    case let(l?, r?): return l < r // Both lhs and rhs are not nil
    case (nil, _): return false    // Lhs is nil
    case (_?, nil): return true    // Lhs is not nil, rhs is nil
    }
}

print(sortedArray) // [Optional("a"), Optional("b"), nil, nil]

Это работает с любым массивом необязательных сопоставимых элементов и позволяет избежать использования «магического большого»" ценности.Компаратор может быть реализован как универсальная функция:

func compareOptionalsWithLargeNil<T: Comparable>(lhs: T?, rhs: T?) -> Bool {
    switch (lhs, rhs) {
    case let(l?, r?): return l < r // Both lhs and rhs are not nil
    case (nil, _): return false    // Lhs is nil
    case (_?, nil): return true    // Lhs is not nil, rhs is nil
    }
}

print(["b", nil, "a", nil].sorted(by: compareOptionalsWithLargeNil))
// [Optional("a"), Optional("b"), nil, nil]

print([2, nil, 1].sorted(by: compareOptionalsWithLargeNil))
// [Optional(1), Optional(2), nil]

print([3.0, nil, 1.0].sorted(by: compareOptionalsWithLargeNil))
// [Optional(1.0), Optional(3.0), nil]

print([Date(), nil, .distantPast, nil, .distantFuture].sorted(by: compareOptionalsWithLargeNil))
// [Optional(0000-12-30 00:00:00 +0000), Optional(2018-11-22 13:56:03 +0000),
//  Optional(4001-01-01 00:00:00 +0000), nil, nil]
0 голосов
/ 22 ноября 2018

Один nil неотличим от другого.Поэтому, если у вас есть работающее решение, которое может сортироваться по вашему желанию, за исключением того, что записи nil заканчиваются в начале, используйте его, а затем удалите записи nil и добавьте то же количество записей nil в конец.

Пример:

    var arr : [String?] = [nil, "b", nil, "a", nil]
    arr = arr.sorted{ $0 ?? "" < $1 ?? "" }
    if let ix = arr.firstIndex(where: {$0 != nil}) {
        arr = arr.suffix(from: ix) + Array(repeating: nil, count: ix)
    }
    // [Optional("a"), Optional("b"), nil, nil, nil]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...