Почему при снятии акцентов/диакритических знаков

Я использую этот метод для удаления акцентов из строк:

static string RemoveAccents(string input)
{
    string normalized = input.Normalize(NormalizationForm.FormKD);
    StringBuilder builder = new StringBuilder();
    foreach (char c in normalized)
    {
        if (char.GetUnicodeCategory(c) !=
        UnicodeCategory.NonSpacingMark)
        {
            builder.Append(c);
        }
    }
    return builder.ToString();
}

но этот метод оставляет đ как đ и не меняет его на d, хотя d является его базой char. вы можете попробовать его с помощью этой вводной строки "æøåáâăäĺćččęęěěíěďđďđďđďđňňňőőőőůůůűűýţ"

Что такого особенного в письме?

Ответы

Ответ 1

Ответ за то, почему он не работает, заключается в том, что утверждение, что "d является его базой char", является ложным. U + 0111 (LATIN SMALL LETTER D WITH STROKE) имеет категорию Unicode "Letter, Lowercase" и не имеет разбиения на разложение (т.е. Не разлагается до "d", за которым следует комбинационная метка).

"đ".Normalize(NormalizationForm.FormD) просто возвращает "đ", который не удаляется контуром, потому что он не является меткой без пробела.

Аналогичная проблема будет существовать для "ø" и других букв, для которых Unicode не обеспечивает отображение разложения. (И если вы пытаетесь найти "лучший" ASCII-символ для представления буквы Unicode, этот подход не будет работать вообще для кириллических, греческих, китайских или других нелатинских алфавитов, вы также столкнетесь с проблемами, если вы хотели транслитерировать "ß" на "ss", например. Использование библиотеки типа UnidecodeSharp может помочь.)

Ответ 2

Я должен признать, что я не уверен, почему это работает, но он уверен, что

var str = "æøåáâăäĺćçčéęëěíîďđńňóôőöřůúűüýţ";
var noApostrophes = Encoding.ASCII.GetString(Encoding.GetEncoding("Cyrillic").GetBytes(str)); 

= > "aoaaaaalccceeeeiiddnnooooruuuuyt"

Ответ 3

" D с инсультом" (Википедия) используется на нескольких языках и, по-видимому, считается во всех них отдельной буквой - - и поэтому он остается неизменным.

Ответ 4

это должно работать

    private static String RemoveDiacritics(string text)
    {
        String normalized = text.Normalize(NormalizationForm.FormD);
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < normalized.Length; i++)
        {
            Char c = normalized[i];
            if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
                sb.Append(c);
        }

        return sb.ToString();
    }