Swift how to sort dict keys by byte value and not alphabetically?

前端 未结 1 2027
我寻月下人不归
我寻月下人不归 2021-01-23 20:32

I\'m using a for loop to create a string of a dicts keys and values. Unfortunately swift behaves differently on Mac and Linux.

for key in parameters.keys.sorted()

1条回答
  •  闹比i
    闹比i (楼主)
    2021-01-23 21:15

    On Apple platforms, Swift strings comparison is a lexicographical comparison of Unicode scalar values, based on the so-called "Unicode Normalization Form D", see How String Comparison happens in Swift or What does it mean that string and character comparisons in Swift are not locale-sensitive? for details.

    On Linux, the sort order is different. That is a known problem ([String] sort order varies on Darwin vs. Linux) and should be fixed in Swift 4.

    If you only care about ASCII characters then a possible approach would be to compare the UTF-8 representation of the strings:

    func utf8StringCompare(s1: String, s2: String) -> Bool {
        let u1 = s1.utf8
        let u2 = s2.utf8
        for (x, y) in zip(u1, u2) {
            if x < y { return true }
            if x > y { return false }
        }
        return u1.count < u2.count
    }
    
    
    let s = ["AWT", "Ast"].sorted(by: utf8StringCompare)
    print(s) // ["AWT", "Ast"]
    

    This gives identical results on Apple platforms and on Linux.

    But note that this is not the default sort order for Swift Strings on Apple platforms. To replicate that on Linux (before it is fixed in Swift 4), the following algorithm would work:

    func unicodeStringCompare(s1: String, s2: String) -> Bool {
        let u1 = s1.decomposedStringWithCanonicalMapping.unicodeScalars
        let u2 = s2.decomposedStringWithCanonicalMapping.unicodeScalars
        for (x, y) in zip(u1, u2) {
            if x.value < y.value { return true }
            if x.value > y.value { return false }
        }
        return u1.count < u2.count
    }
    
    let someStrings = ["a", "b", "e", "f", "ä", "é"].sorted(by: unicodeStringCompare)
    print(someStrings) // ["a", "ä", "b", "e", "é", "f"]
    

    0 讨论(0)
提交回复
热议问题