Ответ 1
Это зависит от требований. Для большинства применений, нормализация к NFD и последующая фильтрация всех комбинаций символов. В некоторых случаях нормализация к NFKD более подходит (если вы также хотите удалить некоторые дополнительные различия между символами).
Некоторые другие отличия не будут улавливаться этим, особенно ласковыми штрихами. Там также нет четкого неязыкового метода для некоторых (следует ли считать, что ł эквивалентно l или w?), Поэтому вам может потребоваться настроить вне этого.
Также есть случаи, когда NFD и NFKD работают не так, как ожидалось, чтобы обеспечить согласованность между версиями Unicode.
Следовательно:
public static IEnumerable<char> RemoveDiacriticsEnum(string src, bool compatNorm, Func<char, char> customFolding)
{
foreach(char c in src.Normalize(compatNorm ? NormalizationForm.FormKD : NormalizationForm.FormD))
switch(CharUnicodeInfo.GetUnicodeCategory(c))
{
case UnicodeCategory.NonSpacingMark:
case UnicodeCategory.SpacingCombiningMark:
case UnicodeCategory.EnclosingMark:
//do nothing
break;
default:
yield return customFolding(c);
break;
}
}
public static IEnumerable<char> RemoveDiacriticsEnum(string src, bool compatNorm)
{
return RemoveDiacritics(src, compatNorm, c => c);
}
public static string RemoveDiacritics(string src, bool compatNorm, Func<char, char> customFolding)
{
StringBuilder sb = new StringBuilder();
foreach(char c in RemoveDiacriticsEnum(src, compatNorm, customFolding))
sb.Append(c);
return sb.ToString();
}
public static string RemoveDiacritics(string src, bool compatNorm)
{
return RemoveDiacritics(src, compatNorm, c => c);
}
Здесь мы по умолчанию для проблемных случаев, упомянутых выше, которые просто игнорируют их. Мы также разделили построение строки из генерации перечисления символов, поэтому нам не нужно расточительно в тех случаях, когда нет необходимости в манипулировании строками результата (скажем, мы собирались написать символы для вывода следующего или сделать еще несколько char -by- char).
Пример для чего-то, где мы хотели также преобразовать ł и Ł в l и L, но не имел других специализированных проблем, которые могли бы использовать:
private static char NormaliseLWithStroke(char c)
{
switch(c)
{
case 'ł':
return 'l';
case 'Ł':
return 'L';
default:
return c;
}
}
Используя это с помощью вышеперечисленных методов, он будет объединяться для удаления штриха в этом случае вместе с разложимой диакритикой.