Преобразование между диакритическими вариантами символа

Я передаю строку в качестве параметра инструменту командной строки, написанному на быстром языке.

У меня проблема с некоторыми символами, содержащими диакритические знаки.

Если я пройду à á ả ã ạ й ё в качестве строкового аргумента внутри приложения я получил à á ả ã ạ й ё. Выглядит так же, но это не так:

      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
Другие вопросы по тегам