Swift中的字符串和字符比较对区域设置敏感是什么意思?

Dmy*_*kin 12 string swift

我开始学习Swift语言,我非常好奇Swift中的字符串和字符比较对语言环境不敏感是什么意思?这是否意味着所有字符都以UTF-8字符存储在Swift中?

Mar*_*n R 26

(现在为Swift 3更新了所有代码示例.)

比较Swift字符串与<基于所谓的"Unicode规范化形式D"(可用其计算 decomposedStringWithCanonicalMapping)进行字典比较

例如,分解

"ä" = U+00E4 = LATIN SMALL LETTER A WITH DIAERESIS
Run Code Online (Sandbox Code Playgroud)

是两个Unicode代码点的序列

U+0061,U+0308 = LATIN SMALL LETTER A + COMBINING DIAERESIS
Run Code Online (Sandbox Code Playgroud)

出于演示目的,我编写了一个小的String扩展,它将String的内容转储为Unicode代码点数组:

extension String {
    var unicodeData : String {
        return self.unicodeScalars.map {
            String(format: "%04X", $0.value)
            }.joined(separator: ",")
    }
}
Run Code Online (Sandbox Code Playgroud)

现在让我们拿一些字符串,用它们排序<:

let someStrings = ["??", "ä?", "?x", "äx"].sorted()
print(someStrings)
// ["a", "ã", "?", "ä", "?", "b"]
Run Code Online (Sandbox Code Playgroud)

并在排序数组中转储每个字符串的Unicode代码点(原始和分解形式):

for str in someStrings {
    print("\(str)  \(str.unicodeData)  \(str.decomposedStringWithCanonicalMapping.unicodeData)")
}
Run Code Online (Sandbox Code Playgroud)

输出

äx  00E4,0078  0061,0308,0078
?x  01DF,0078  0061,0308,0304,0078
??  01DF,03C8  0061,0308,0304,03C8
ä?  00E4,03C8  0061,0308,03C8
Run Code Online (Sandbox Code Playgroud)

很好地表明,比较是通过分解形式的Unicode代码点的字典顺序完成的.

对于包含多个字符的字符串也是如此,如以下示例所示.同

let someStrings = ["??", "ä?", "?x", "äx"].sorted()
Run Code Online (Sandbox Code Playgroud)

上面循环的输出是

äx  00E4,0078  0061,0308,0078
?x  01DF,0078  0061,0308,0304,0078
??  01DF,03C8  0061,0308,0304,03C8
ä?  00E4,03C8  0061,0308,03C8
Run Code Online (Sandbox Code Playgroud)

意思就是

"äx" < "?x", but "ä?" > "??"
Run Code Online (Sandbox Code Playgroud)

(这对我来说至少是意料之外的).

最后让我们将它与区域设置敏感的排序进行比较,例如瑞典语:

let locale = Locale(identifier: "sv") // svenska
var someStrings = ["?", "ä", "ã", "a", "?", "b"]
someStrings.sort {
    $0.compare($1, locale: locale) == .orderedAscending
}

print(someStrings)
// ["a", "?", "ã", "b", "ä", "?"]
Run Code Online (Sandbox Code Playgroud)

如您所见,结果与Swift <排序不同.

  • 添加/详细信息(“官方”参考:来自开源):来自 [String.swift 源代码](https://github.com/apple/swift/blob/master/stdlib/public/core/String.swift ) 我们可以看到,例如 `String` 的 `&lt;` 运算符被定义为 `lhs._compareString(rhs) &lt; 0`(使用 `_swift_stdlib_unicode_compare_utf8_utf8` 本身),我们可以通过 https://github.com 跟踪/apple/swift/blob/master/stdlib/public/stubs/UnicodeNormalization.cpp 从 ICU lib 到 `ucol_strcollIter`(请参阅 `MakeRootCollat​​or` 以获取整理器设置);即,使用 [unicode collat​​ion algorithm](http://unicode.org/reports/tr10/)。 (2认同)