Я нашел это в статье Википедии о utf-8:
Сортировка строк UTF-8 как массивы неподписанных байтов приведет к тем же результатам как сортировка их на основе кодовых точек Unicode.
Это привело бы меня полагать, что в целях сравнения (сортировка, двоичный поиск, и т.д.) то, что сравнение двух массивов байтов (т.е. байт байтом как memcmp) utf-8 закодировало строки, даст те же результаты как сравнение фактических строк unicode.
Действительно ли это верно?
Это зависит от того, что вы подразумеваете под "сравнением фактических строк Unicode".
Если вы просто собираетесь сравнивать кодовые точки (как 32-битные числа), а не кодовые точки в кодировке UTF-8, то ответ будет положительным: это даст те же результаты. Сопоставление кодовых точек с байтами в кодировке UTF-8 - один к одному.
Если вы собираетесь выполнять правильное сравнение строк Unicode, а не попутное сравнение UTF-8, то ответ - нет. В Юникоде могут быть разные способы представления одного и того же символа. Например, é может быть представлен (по крайней мере) двумя способами:
U+00e9 (LATIN SMALL LETTER E WITH ACUTE)
, илиU+0065 (LATIN SMALL LETTER E)
с последующим U+0301 (COMBINING ACUTE ACCENT)
. Правильно написанная функция сравнения Unicode будет считать эти два символа идентичными.
Это то же самое, что и кодовая точка для сравнения кодовых точек, то есть такая, которая не обращает внимания на сворачивание регистра, культурный порядок, композицию или что-либо, кроме значения Unicode.
Это довольно бесполезно, если рассматривать строки как часть текста, удобочитаемого человеком, но иногда вы просто хотите иметь возможность поместить строки в и упорядочивание, как некоторые алгоритмы (двоичный поиск, как вы говорите ) требуется последовательный порядок, но детали этого последовательного порядка не имеют значения.
Однако важно отметить, что порядковое сравнение строк, предлагаемое .NET, работает с внутренним UTF-16, который не поддерживает порядок кодовых точек. Если мы сравним строку только с символом U + FF61 и строку только с символом U + 10002, то .NET сохранит последний как суррогатные пары 0xD800 и 0XDC02.
Следовательно:
string.CompareOrdinal("\U0000ff61", "\U00010002");
и
string.Compare("\U0000ff61", "\U00010002", StringComparison.Ordinal);
оба возвращают значения больше нуля, даже несмотря на то, что первое имеет меньшее значение кодовой точки, чем второе (я использовал форму \ U, а не форму \ u, чтобы сделать это более понятным ).
Если под «фактическими строками Unicode» вы подразумеваете строки .NET UTF-16, то ответ на ваш вопрос отрицательный по причине, противоположной той, которая заставляла вас думать, что это может сработать.
Нет, это не так.
Например, À
может быть записано как одна кодовая точка ( U + 00C0
ЛАТИНСКАЯ ЗАГЛАВНАЯ БУКВА A С ТЯЖЕЛЫМ) или как две кодовые точки ( U + 0041
ЛАТИНСКАЯ ЗАГЛАВНАЯ БУКВА A U + 0300
ОБЪЕДИНЕНИЕ МОЩНОГО АКЦЕНТА).
Оба представления должны сравниваться одинаково, но иметь разные байтовые кодировки.
Да, учитывая, что существует взаимно-однозначное соответствие между байтами последовательностей в кодировке UTF-8 и кодовыми точками Unicode.
Однако есть способ сравнить строки Unicode помимо просмотра необработанных кодовых точек. Если вы просто смотрите на кодовые точки - или байты UTF-8 - как на числа, вы упускаете логику сравнения, зависящую от культуры.
Чтобы правильно реализовать сравнение и сортировку для определенного языка и региональных параметров, в .NET следует использовать стандартные функции сравнения строк.
Я нашел это в статье Википедии о utf-8:
Сортировка строк UTF-8 как массивов беззнаковых байтов даст те же результаты, что и сортировка на основе кодовых точек Unicode.
Это наводит меня на мысль, что для целей сравнения (сортировка, двоичный поиск и т.д.) сравнение двух байтовых массивов (т.е. побайтно, как memcmp) строк в кодировке utf-8 даст те же результаты, что и сравнение реальных строк в коде Unicode.
Все зависит от того, что вы подразумеваете под "реальными строками Юникода" и что вы подразумеваете под "сравнением". В .Net Framework строки находятся в UTF-16 форме Юникода. Простое двоичное сравнение между строками UTF-16 даст другой порядок сортировки, чем такое же сравнение между строками UTF-8 и UTF-32 (версия кодовой точки, упомянутая в цитате).
Но двоичное сравнение любой из этих вещей не очень полезно. Вы должны использовать встроенные сравнения с учетом культуры. Это связано с тем, что две одинаковые по смыслу строки могут быть построены из разных последовательностей кодовых точек. Встроенные сравнения учитывают эти моменты.