代码之家  ›  专栏  ›  技术社区  ›  John Montgomery

将nil排序到可选字符串数组的末尾

  •  1
  • John Montgomery  · 技术社区  · 7 年前

    如果我有一个可选字符串数组,并且我想在开始时用nils按升序排序,那么我可以在一行中轻松地进行排序:

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

    但似乎没有任何类似的简单解决方案可以将零排序到零

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

    对于双打,你也可以这样做 greatestFiniteMagnitude ,用于您可以使用的日期 distantFuture

    3 回复  |  直到 7 年前
        1
  •  5
  •   Martin R    7 年前

    您可以提供一个自定义比较器,它考虑 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]
    
        2
  •  1
  •   matt    7 年前

    一个 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]
    
        3
  •  1
  •   Mike Taverne    7 年前

    你的例子 Int 提供线索。如果我们有一个最大字符串值,我们可以插入它。

    这适用于仅包含字母字符的字符串:

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

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