Преобразование между диакритическими вариантами символа
Я передаю строку в качестве параметра инструменту командной строки, написанному на быстром языке.
У меня проблема с некоторыми символами, содержащими диакритические знаки.
Если я пройду
à á ả ã ạ й ё
в качестве строкового аргумента внутри приложения я получил
à á ả ã ạ й ё
. Выглядит так же, но это не так:
func printUnicodeScalars(_ string: String) {
print(string, "->", string.unicodeScalars.map { $0 })
}
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.
Как я могу конвертировать обратно? Как объединить множество символов юникода-скаляров в один.
1 ответ
Я думаю тебе нужно использовать precomposedStringWithCanonicalMapping
. Это преобразует строку в форму нормализации C, которая:
Каноническая декомпозиция с последующей канонической композицией
Пример:
let string = "à á ả ã ạ й ё"
print(string.unicodeScalars.count) // 20
print(string.precomposedStringWithCanonicalMapping.unicodeScalars.count) // 13