Sort nil to the end of an array of optional strings

前端 未结 3 1765
不思量自难忘°
不思量自难忘° 2021-01-14 22:08

If I have an array of optional strings, and I want to sort it in ascending order with nils at the beginning, I can do it easily in a single line:

[\"b\", nil         


        
3条回答
  •  别那么骄傲
    2021-01-14 22:45

    You can provide a custom comparator which considers nil as larger than any non-nil value:

    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]
    

    This works with any array of optional comparable elements, and avoids the usage of “magical large” values. The comparator can be implemented as a generic function:

    func compareOptionalsWithLargeNil(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]
    

提交回复
热议问题