在字符的变音符号变体之间转换

Convert between diacritic variants of a character

我将字符串作为参数传递给用 swift 编写的命令行工具。

我对某些包含变音符号的字符有疑问。

如果我将 à á ả ã ạ й ё 作为行参数传递,在应用程序中我得到 à á ả ã ạ й ё。看起来一样,但不是:

func printUnicodeScalars(_ string: String) {
    print(string, "->", string.unicodeScalars.map { [=10=] })
}
printUnicodeScalars("à á ả ã ạ й ё")
// à á ả ã ạ й ё -> ["\u{00E0}", " ", "\u{00E1}", " ", "\u{1EA3}", " ", "\u{00E3}", " ", "\u{1EA1}", " ", "\u{0439}", " ", "\u{0451}"]
printUnicodeScalars("à á ả ã ạ й ё")
// à á ả ã ạ й ё -> ["a", "\u{0300}", " ", "a", "\u{0301}", " ", "a", "\u{0309}", " ", "a", "\u{0303}", " ", "a", "\u{0323}", " ", "\u{0438}", "\u{0306}", " ", "\u{0435}", "\u{0308}"]

我知道 ASCII 中的变音符号字符可以用不同的方式表示:像单个字符,或者像两个字符的组合:一个字母和一个变音符号。

出于某种原因,命令行工具将第一个变体转换为第二个变体。可能是因为它仅限于 UTF-8。

如何转换回来?喜欢将许多 unicode-scalars 字符合并为一个字符。

我认为你需要使用precomposedStringWithCanonicalMapping. This converts the string to Normalization Form C,即:

Canonical Decomposition, followed by Canonical Composition

示例:

let string = "à á ả ã ạ й ё"
print(string.unicodeScalars.count) // 20
print(string.precomposedStringWithCanonicalMapping.unicodeScalars.count) // 13