Как проверить, есть ли у символа Unicode диакритические знаки в .Net?

Я разрабатываю эвристику для автоматического определения языка и хотел бы узнать, есть ли у данной буквы диакритические знаки (например, "Рааи Êóëüòóðà" - все буквы имеют диакритические знаки). Было бы лучше, если бы я мог также получить тип диакритического знака, если это возможно.

Я просмотрел UnicodeCategory enum, но не нашел здесь ничего, что могло бы мне помочь.


person Alexander Galkin    schedule 19.02.2012    source источник
comment
Буква eth (Ð) не имеет диакритического знака. В Юникоде это основной символ; штрих не считается диакритическим знаком. Таким образом, вы можете переформулировать свою цель (и, возможно, объяснить, какую конкретную проблему она решит, поскольку могут быть лучшие подходы).   -  person Jukka K. Korpela    schedule 19.02.2012
comment
Разложение — это последнее, что вы хотите сделать. Сочетание определенной буквы с определенным диакритическим знаком является сильным селектором языка. Просто создайте таблицы частот заранее. Но есть много языков, которые почти не используют диакритические знаки. Например, вы не сможете отличить английский, голландский и итальянский языки. Вам понадобится словарь, чтобы это действительно работало. Хранение, скажем, 100 самых распространенных слов будет иметь большое значение.   -  person Hans Passant    schedule 19.02.2012


Ответы (1)


Один из возможных способов - нормализовать его к форме, в которой буквы и их диакритические знаки записываются как несколько кодовых точек. Затем проверьте, есть ли у вас буква, за которой следуют ударения.

Адаптация из Как удалить диакритические знаки (акценты) из строки в .NET?, вы можете нормализовать с помощью Normalize(NormalizationForm.FormD) и проверить наличие диакритических знаков с помощью UnicodeCategory.NonSpacingMark.

bool IsLetterWithDiacritics(char c)
{
    var s = c.ToString().Normalize(NormalizationForm.FormD);
    return (s.Length > 1)  &&
           char.IsLetter(s[0]) &&
           s.Skip(1).All(c2 => CharUnicodeInfo.GetUnicodeCategory(c2) == UnicodeCategory.NonSpacingMark);
}
person CodesInChaos    schedule 19.02.2012
comment
Если вам нужна проверка истинности/ложности, вы можете просто нормализовать ее до FormD или чего бы то ни было, и просто проверить, длиннее ли строка, чем оригинал. - person Joakim Johansson; 19.02.2012
comment
@JoakimJohansson Я бы не удивился, если бы были другие глифы, которые разлагаются в FormD, но не являются буквами с акцентом. Но я не знаю, насколько хорошо моя идея поведет себя и на них. - person CodesInChaos; 19.02.2012
comment
@JoakimJohansson Один большой класс символов, которые ваш алгоритм считает имеющими диакритические знаки, - это корейские символы хангыль. Они состоят из нескольких частей, которые разлагаются, но не являются диакритическими знаками. Некоторые примеры: , , . Затем есть математические символы, такие как: , , , И, наконец, несколько, которые я вообще не знаю: - person CodesInChaos; 19.02.2012
comment
Диакритические знаки — это только подмножество комбинированных символов без пробелов. Например, символ Юникода "\u0CBF" равен UnicodeCategory.NonSpacingMark, но он не диакритический знак. - person Paolo Moretti; 19.02.2012
comment
@PaoloMoretti Входные данные должны представлять собой разложение одной кодовой точки, а первая кодовая точка в разложении должна быть буквой. Так что ваш пример не нарушает алгоритм. Я не уверен, что есть ложные срабатывания. В арабском письме есть несколько странных падежей, но я не знаю, диакритические знаки это или нет. Но если вы знаете лучший алгоритм, я открыт для предложений. - person CodesInChaos; 19.02.2012