Swift如何按字节值而不是按字母顺序对字典...

codeday· 2019-10-13
本文来自 codeday ,作者 codeday
我正在使用for循环来创建由dict键和值组成的字符串.
不幸的是,Swift在Mac和Linux上的行为有所不同.

用于输入parameters.keys.sorted(){…}

我想按字节值而不是按字母顺序对键排序,小写参数应在大写字母之后列出.

因此,像“ AWT”这样的键应该位于像“ Ast”这样的键之前.

最佳答案
在Apple平台上,Swift字符串比较是基于所谓的“ Unicode规范化形式D”的Unicode标量值的字典比较,请参阅
详情请参阅How String Comparison happens in SwiftWhat does it mean that string and character comparisons in Swift are not locale-sensitive?.

在Linux上,排序顺序不同.那是一个已知的问题
([String] sort order varies on Darwin vs. Linux),应在Swift 4中修复.

如果您只关心ASCII字符,则可能的方法是
将比较字符串的UTF-8表示形式:

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"]

这在Apple平台和Linux上给出了相同的结果.

但是请注意,这不是Swift字符串的默认排序顺序
在Apple平台上.要在Linux上复制该代码(在Swift 4中已修复),请执行以下操作
算法将起作用:

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"]