2008-11-18 11 views
14

C'est surtout une question théorique dont je suis très curieux. (Je n'essaie pas de le faire en le codant moi-même ou quoi que ce soit, je ne réinvente pas les roues.)Comment définir les chaînes en majuscules/minuscules dans Unicode?

Ma question est de savoir comment la table majuscule/minuscule d'équivalence fonctionne pour Unicode. Par exemple, si je devais le faire en ASCII, je prendrais un caractère, et s'il tombe avec la gamme [a-z], je ferais la somme de la différence entre A et a.

S'il ne tombe pas dans cette plage, j'aurais une petite table d'équivalence pour les 10 caractères accentués plus ñ. (Ou, je pourrais juste avoir un tableau d'équivalence complet avec 256 entrées, dont la plupart seraient les mêmes que l'entrée)

Cependant, je suppose qu'il y a une meilleure façon de spécifier les équivalences en Unicode, étant donné qu'il y a des centaines de milliers de caractères, et qu'en théorie, une nouvelle langue ou un ensemble de caractères peut être ajouté (et je m'attends à ce que vous n'ayez pas besoin de patcher les fenêtres quand cela arrive).

Windows a-t-il une énorme table d'équivalence codée en dur pour chaque caractère? Ou comment cela est-il mis en œuvre?

Une question connexe est de savoir comment SQL Server implémente les requêtes insensibles à la majuscule et insensible à la casse basées sur Unicode. A-t-il une table interne qui lui indique que E E È et Ë sont tous équivalents à "e"?

Cela ne sonne pas très vite quand il s'agit de comparer des chaînes.

Comment accède-t-il rapidement aux index? Est-ce qu'il indexe déjà les valeurs converties en leurs caractères "de base", correspondant au classement de ce champ?

Est-ce que quelqu'un connaît les internes pour ces choses?

Merci!

+0

Je pense que vous aurez besoin de patcher les fenêtres si elles ont ajouté un nouveau jeu de caractères à unicode, mais que ce serait un patch de très faible priorité, car au départ, personne n'utiliserait ces caractères. –

+0

"une petite table d'équivalence pour les 10 caractères accentués plus ñ" - vous devez comprendre que "petit" signifie environ 100 fois plus grand que vous pensiez que cela signifiait. –

+1

Je ne suis pas tout à fait sûr que je comprends pourquoi toutes les variantes sur e que je ne peux pas taper avec mon clavier facilement tous égaux "e". Je peux le comprendre du point de vue de la base de données (pour la recherche en ignorant les accents spéciaux) mais d'un point de vue linguistique, ce sont tous des caractères différents ... –

Répondre

11

Il existe un fichier de mappage qui contient tous les mappages de cas ayant un rapport de mappage 1: 1. Généralement les systèmes d'exploitation/frameworks/bibliothèques supportent une version spécifique d'Unicode, et puisque ce fichier de mappages de cas est versionné, vous obtiendrez les mappages pour n'importe quelle version d'Unicode votre OS/framework/bibliothèque/support particulier.

Pour plus d'informations sur les correspondances de cas Unicode, voir: http://www.unicode.org/faq/casemap_charprop.html

3

La plupart des systèmes d'écriture ne sont pas des lettres majuscules et minuscules séparées. Selon Wikipédia, les exceptions incluent "alphabets romains, grecs, cyrilliques et arméniens".

Il n'y a donc pas beaucoup de lettres à s'inquiéter. This page montre que de larges plages de caractères suivent un schéma simple d'ajout de 1 à une majuscule pour obtenir l'équivalent en minuscules (bien qu'il y ait bien sûr quelques exceptions).

16

Je vais aborder la partie MS SQL Server de cette question, mais la réponse "correcte" dépend réellement de la ou des langues supportées et de l'application. Lorsque vous créez une table dans SQL Server, chaque zone de texte dispose d'un classement implicitement ou explicitement spécifié. Cela affecte à la fois l'ordre de tri et le comportement de comparaison. La valeur par défaut, pour la plupart des paramètres régionaux anglais (US), est Latin1_General_CI_AS ou Latin 1, insensible à la casse, Accent-Sensitive. Cela signifie que, par exemple, a = A, mais a! = Ä et a! = Ä.Vous pouvez également utiliser l'accent-insensible (Latin1_General_CI_AI) qui traite toutes les variations diacritiques de "A" comme égales.

Certains paramètres régionaux prennent en charge d'autres catégories de comparaison; par exemple, le français commande des mots contenant des signes diacritiques un peu différemment de l'allemand. Le turc considère un i sans point et un pointillé i sémantiquement différent, donc je et moi ne correspondons pas même avec des comparaisons insensibles à la casse si vous utilisez un classement turc, insensible à la casse et sensible aux accents.

Vous pouvez modifier le classement par base de données, par table, par champ et, avec un certain coût, même par requête. Ma compréhension est que les indices se normalisent en fonction de l'ordre de classement spécifié, ce qui signifie que l'index conserve une version aplatie de la chaîne d'origine. Par exemple, avec des collations insensibles à la casse, Apple et Apple sont stockés en tant que pomme. Les requêtes sont aplanies avec le même classement avant la recherche. En japonais, il y a une autre catégorie de normalisation, où les caractères pleine largeur et demi-largeur comme ア = ア, et dans certains cas, deux caractères demi-largeur sont aplatis en un seul caractère sémantiquement équivalent (バ = バ). Enfin, pour certaines langues, il existe une autre boule de cire avec des caractères composites, où des caractères diacritiques isolés peuvent être composés avec d'autres caractères (par exemple, le tréma dans ä est un caractère, composé avec la forme simple a). Le vietnamien, le thaïlandais et quelques autres langues ont des variations de cette catégorie. S'il y a une forme canonique, la normalisation Unicode permet de traiter les formes composées et décomposées comme équivalentes. La normalisation Unicode est généralement appliquée avant toute comparaison. Pour résumer, pour une comparaison insensible à la casse, vous faites quelque chose comme vous le feriez en comparant les chaînes ASCII: aplatissez les côtés gauche et droit de la comparaison "en minuscules" (par exemple), puis comparez les tableau en tant que tableau binaire. La différence est que vous devez 1) normaliser les chaînes à la même forme unicode (kC ou kD) 2) normaliser les chaînes à la même affaire selon les règles de cette locale 3) normaliser les accents en fonction de l'accent 4) comparer selon une comparaison binaire 4) le cas échéant, comme dans le cas du tri, comparer en utilisant d'autres règles secondaires et ternaires de tri, qui incluent des choses analogues à des choses comme "Mc" trie avant "M" dans certaines langues.

Et oui, Windows stocke des tables pour toutes ces règles. Vous ne les obtenez pas tous par défaut dans chaque installation, à moins que vous ne les ajoutiez avec la prise en charge de la prise en charge linguistique en Asie de l'Est et des scripts complexes à partir du panneau de configuration.

+1

Wow. J'aimerais pouvoir vous donner plus de votes. Merci!! –

1

La bonne réponse est un peu plus compliquée, selon ce que vous essayez de faire. Lorsque vous comparez des chaînes de caractères, pour trier ou rechercher des applications, l'algorithme correct à utiliser est spécifié dans UTS #10: "Unicode Collation Algorithm". L'insensibilité à la casse fait partie du mélange, mais il existe différentes façons de représenter un grand nombre de caractères, et les applications doivent souvent traiter les différentes représentations comme équivalentes.

Les règles de tri dépendent des paramètres régionaux. Ceci est principalement un problème lorsque vous triez des résultats pour l'affichage à un utilisateur. Ignorer les règles peut frustrer les utilisateurs et même entraîner des failles de sécurité.

Si vous essayez simplement de mettre des mots en majuscule à des fins d'affichage, les règles peuvent également être difficiles; il y a des conversions un-à-plusieurs et d'autres problèmes. Selon les paramètres régionaux, la même lettre peut être mise en majuscule différemment. La position de la lettre dans un mot peut faire la différence. Il y a aussi une notion distincte de "cas de titre", où vous voulez simplement mettre en majuscule la première lettre de chaque mot. Parfois, le titre d'un personnage n'est pas le même que le majuscule.

Questions connexes