Как установить строки в верхний / нижний регистр в Юникоде? - PullRequest
14 голосов
/ 18 ноября 2008

Это в основном теоретический вопрос, который мне просто очень интересен. (Я не пытаюсь сделать это, кодируя это сам или что-то, я не изобретаю колеса.)

Мой вопрос заключается в том, как работает таблица эквивалентов в верхнем / нижнем регистре для Unicode.

Например, если бы мне пришлось делать это в ASCII, я бы взял символ, и если он выпал бы в пределах диапазона [a-z], я бы суммировал разницу между A и a.

Если он не попадает в этот диапазон, у меня будет небольшая таблица эквивалентности для 10 или около того акцентированных символов плюс -. (Или я мог бы просто иметь массив полной эквивалентности с 256 записями, большинство из которых были бы такими же, как входные данные)

Тем не менее, я предполагаю, что есть лучший способ задания эквивалентностей в Юникоде, учитывая, что есть сотни тысяч символов, и что теоретически можно добавить новый язык или набор символов (и я ожидая, что вам не нужно будет исправлять окна, когда это произойдет).

Есть ли в Windows огромная жестко закодированная таблица эквивалентности для каждого символа? Или как это реализовано?

Смежный вопрос заключается в том, каким образом SQL Server реализует запросы без учета акцента и без учета регистра на основе Unicode. Есть ли у него внутренняя таблица, которая сообщает, что все é è E É È и equivalent эквивалентны "e"?

Это звучит не очень быстро, когда дело доходит до сравнения строк.

Как быстро получить доступ к индексам? Индексирует ли уже значения, преобразованные в их «базовые» символы, соответствующие сопоставлению этого поля?

Кто-нибудь знает внутренности для этих вещей?

Спасибо!

Ответы [ 4 ]

16 голосов
/ 18 ноября 2008

Я собираюсь обратиться к части MS SQL Server в этом вопросе, но «правильный» ответ на самом деле зависит от поддерживаемого языка (языков) и приложения.

Когда вы создаете таблицу в SQL Server, каждое текстовое поле имеет неявно или явно заданное сопоставление. Это влияет как на порядок сортировки, так и на поведение сравнения. По умолчанию для большинства английских (США) локалей используется Latin1_General_CI_AS или Latin 1, без учета регистра, с учетом акцента. Это означает, что, например, a = A, но a! = Ä и a! = Ä. Вы также можете использовать нечувствительный к акценту (Latin1_General_CI_AI), который рассматривает все диакритические вариации «A» как равные.

Некоторые локали поддерживают другие категории сравнения; например, французский порядок слов, содержащих диакритические знаки, несколько отличается от немецкого. По-турецки семантически разные точки без точек и я, поэтому я и я не совпадаем даже с нечувствительными к регистру сравнениями, если вы используете турецкую, без учета регистра и с сортировкой.

Вы можете изменить параметры сортировки для каждой базы данных, для каждой таблицы, для каждого поля и, с некоторыми затратами, даже для каждого запроса. Насколько я понимаю, индексы нормализуются в соответствии с указанным порядком сортировки, что означает, что в основном индекс сохраняет сглаженную версию исходной строки. Например, при сортировке без учета регистра Apple и apple хранятся как apple. Запросы перед поиском сводятся с одинаковым сопоставлением.

В японском языке есть еще одна категория нормализации, где символы полной ширины и полуширины, такие как ア = ア, а в некоторых случаях два символа полуширины сведены в один семантически эквивалентный символ (バ = バ). Наконец, для некоторых языков есть еще один шарик воска с составными символами, где отдельные диакритические знаки могут быть составлены с другими символами (например, умлаут в ä - один символ, составленный с простой формой a). Вьетнамский, тайский и некоторые другие языки имеют вариации этой категории. Если есть каноническая форма, нормализация Unicode позволяет составным и разложенным формам рассматриваться как эквивалентные. Нормализация Unicode обычно применяется перед выполнением любых сравнений.

Чтобы подвести итог, для сравнения без учета регистра вы делаете что-то похожее на сравнение строк в диапазоне ASCII: сгладьте левую и правую часть сравнения «в нижний регистр» (например), затем сравните массив в виде двоичного массива. Разница в том, что вам нужно 1) нормализовать строки в той же форме Unicode (KC или KD) 2) нормализовать строки в одном и том же случае в соответствии с правилами этой локали 3) нормализовать акценты в соответствии с правилами чувствительности к акценту 4) сравнить согласно бинарному сравнению 4) если применимо, например, в случае сортировки, сравните, используя дополнительные вторичные и троичные правила сортировки, которые включают в себя вещи, аналогичные таким вещам, как сортировка «Mc» перед «M» в некоторых языках.

И да, Windows хранит таблицы для всех этих правил. Вы не получаете все из них по умолчанию в каждой установке, если только вы не добавили поддержку для них с поддержкой восточноазиатских языков и поддержкой сложных сценариев из панели управления.

12 голосов
/ 18 ноября 2008

Существует файл сопоставления, который содержит все сопоставления наблюдений с соотношением сопоставления 1: 1. Обычно операционные системы / фреймворки / библиотеки поддерживают определенную версию Unicode, и, поскольку этот файл сопоставлений case является версионным, вы получите сопоставления для любой версии Unicode для вашей конкретной ОС / framework / library / любой другой поддерживаемой.

Для получения дополнительной информации о сопоставлениях регистров Unicode см .: http://www.unicode.org/faq/casemap_charprop.html

3 голосов
/ 18 ноября 2008

Большинство систем письма не имеют отдельных прописных и строчных букв. Согласно Википедии, исключения включают «латинский, греческий, кириллический и армянский алфавиты».

Так что не так много писем для беспокойства. На этой странице показано, что большие диапазоны символов следуют простой схеме добавления 1 к символу в верхнем регистре, чтобы получить эквивалент в нижнем регистре (хотя, конечно, есть некоторые исключения).

1 голос
/ 19 ноября 2008

Правильный ответ немного сложнее, в зависимости от того, что вы пытаетесь сделать.

При сравнении строк символов для сортировки или поиска приложений правильный алгоритм для использования указывается в UTS # 10: «Алгоритм сопоставления Unicode». Чувствительность к регистру является частью микса различные способы представления множества символов, и приложениям часто приходится рассматривать различные представления как эквивалентные.

Правила сортировки зависят от локали. Это в основном проблема, когда вы сортируете результаты для отображения пользователю. Игнорирование правил может расстроить пользователей и даже привести к уязвимостям безопасности.

Если вы просто пытаетесь использовать слова с заглавной буквы для отображения, правила тоже могут быть хитрыми; есть конверсии один ко многим и другие проблемы. В зависимости от локали одна и та же буква может начинаться с заглавной буквы по-разному. Позиция буквы в слове может иметь значение. Существует также отдельное понятие «регистр заголовка», где вы просто хотите использовать заглавные буквы первой буквы каждого слова. Иногда регистр заглавия символа не совпадает с заглавным.

...