Как свернуть/нормализовать лигатурные символы в C# для сравнения строкC#

Место общения программистов C#
Ответить
Anonymous
 Как свернуть/нормализовать лигатурные символы в C# для сравнения строк

Сообщение Anonymous »

В данный момент я изучаю некоторые из наиболее эзотерических аспектов сравнения строк (я зашёл в кроличью нору, и, похоже, конца этому не видно!).
Мне хотелось бы знать, как сравнить строку, содержащую символы с лигатурами, с канонической версией без лигатур (представьте себе приложение для изучения французского языка, которое позволяет пользователю вводить oeuf или œuf взаимозаменяемо). Мне кажется, это называется «складыванием», но я могу ошибаться.
Я пробовал нормализовать свои строки с помощью NFKD, который, как я думал, разложит символ на составные части, но только некоторые кодовые точки Unicode поддерживают декомпозицию. (Конечно, мой пример символа «œ» этого не делает, что привело к частым выдергиваниям за волосы.)
Например:

Код: Выделить всё

using System.Text;
using System.Globalization;

// This character does not support decomposition.
string str1 = "\u0153"; // œ (LATIN SMALL LIGATURE OE)
string str2 = "oe";
string str1norm = str1.Normalize(NormalizationForm.FormKD);

Console.WriteLine(str1norm.IsNormalized()); // True
Console.WriteLine(str1norm.Equals(str2));   // False
Console.WriteLine(str1norm.Length);         // 1

// This character supports decomposition.
str1 = "\uFB06"; // st (LATIN SMALL LIGATURE ST)
str2 = "st";
str1norm = str1.Normalize(NormalizationForm.FormKD);

Console.WriteLine(str1norm.IsNormalized()); // True
Console.WriteLine(str1norm.Equals(str2));   // True
// (Non-normalized comparison.) True in most locales, but not all (see below)
Console.WriteLine(str1.Equals(str2, StringComparison.CurrentCultureIgnoreCase));
Console.WriteLine(str1norm.Length);         // 2
Ссылки на два символа Юникода: Если только некоторые лигатуры разбираются, у меня есть пара вопросов:
  • Как мне это определить, не проверяя вручную все кодовые точки Юникода?
  • Могу ли я выполнить сравнение строк с канонической версией строки без необходимости создания словаря все неразложимые символы и их развернутые формы? Я имею в виду, что мне нравится печатать, но не так уж сильно.
  • (Бонусный раунд.) Почему некоторые многосимвольные кодовые точки можно разложить (например, в примере с лигатурой 'st'), а некоторые нет ? Есть ли что-то особенное в таких символах, как «œ»?
Редактировать: я провел дополнительное исследование и такие символы, как «œ» или Немецкие «диез» считаются отдельными буквами, а не составными буквами. Они представляют собой текущее использование в этих языках, даже если исторически вещи могли развиваться из разных представлений. Юникод учитывает текущее использование, поэтому имеет смысл пометить их как неразлагаемые.
В качестве последней иллюстрации моего «что-на-земле-происходит-происходит» ?" с точки зрения мышления на данный момент, 'st' эквивалентно 'st' без нормализации в 862 локалях на моем ПК, при этом сравнение строк завершается неудачей только в 7, причем эти локали ошибочны: Все это очень интересно, но явная кажущаяся произвольность всего этого немного ошеломляет :) Что касается насколько я знаю, в Афаре и Сахо письменные формы основаны на латинице, но я предполагаю, что их кодовые страницы Unicode менее популярны и могут просто отсутствовать записи для лигатур, которые присутствуют в других.
< em>Наконец, наконец, односимвольный символ 'f' и его разложенная форма 'st' равны в культуре .NET Invariant, но только если регистр игнорируется:

Код: Выделить всё

//...continuing from prior code...
Console.WriteLine(str1.Equals(str2, StringComparison.InvariantCulture));           // False
Console.WriteLine(str1.Equals(str2, StringComparison.InvariantCultureIgnoreCase)); // True
Это озадачивает, потому что обе строки написаны строчными буквами.
(Я знаю: «Просто нормализуйте свою строку и забудьте, что вы когда-либо видели это, Дэйв». Но я все равно думаю, что интересно узнать, почему это происходит.)
Спасибо, что уделили время.

Подробнее здесь: https://stackoverflow.com/questions/785 ... omparisons
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»