Comment dois-je faire un casse comparaison de chaînes de caractères?
Comment puis-je faire de la casse comparaison de chaînes de caractères en Python?
Je tiens à encapsuler comparaison régulière des chaînes à un référentiel de chaîne à l'aide dans un très simple et Pythonic façon. Je voudrais aussi avoir la capacité à rechercher des valeurs dans une dict haché par les chaînes de l'utilisation de python chaînes.
Vous devez vous connecter pour publier un commentaire.
En supposant que les chaînes ASCII:
Σίσυφος
etΣΊΣΥΦΟΣ
, alors votre approche ne tient pas, car ceux-ci sont censés être de la même affaire sans la moindre sensibilité.'ß'.lower() == 'SS'.lower()
est Faux."fish".casefold() == "Fish".casefold()
les travaux, tandis que.lower()
échoue ici. S'il peut y avoir des cas même.casefold()
n'est pas suffisantComparaison de chaîne de caractères dans une casse manière semble comme quelque chose de banal, mais il ne l'est pas. Je serai à l'aide de Python 3, depuis le Python 2 est sous-développé ici.
La première chose à noter, il que le cas-la suppression des conversions unicode ne sont pas triviales. Il y a du texte pour lequel
text.lower() != text.upper().lower()
, comme"ß"
:Mais disons que vous vouliez caselessly comparer
"BUSSE"
et"Buße"
. Heck, vous avez probablement vous aussi souhaitez comparer"BUSSE"
et"BUẞE"
égalité - c'est la nouvelle forme de capital. La méthode recommandée consiste à utilisercasefold
:N'utilisez pas simplement
lower
. Sicasefold
n'est pas disponible, faire.upper().lower()
aide (mais seulement un peu).Alors vous devriez envisager d'accents. Si votre police rendu est bon, vous pensez probablement
"ê" == "ê"
- mais il n'a pas d':C'est parce qu'ils sont en fait
La façon la plus simple de traiter cette question est
unicodedata.normalize
. Vous voudrez probablement utiliser NFKD à la normalisation, mais n'hésitez pas à consulter la documentation. Alors on nePour finir, voici ce qui est exprimé dans les fonctions de:
x.casefold() == y.casefold()
pour la casse des comparaisons (et, plus important encore,x == y
pour la casse).NFD(toCasefold(NFD(str)))
sur les deux côtés et (D147, compatibilité)NFKD(toCasefold(NFKD(toCasefold(NFD(X)))))
sur les deux côtés. Il précise l'intérieurNFD
est le seul à gérer un certain grec caractère accentué. Je suppose que c'est sur le bord de cas.casefold
fonctionnalité.À l'aide de Python 2, appelant
.lower()
sur chaque chaîne Unicode ou un objet......fonctionne la plupart du temps, mais en effet ne fonctionne pas dans le les situations @tchrist a décrit.
Supposons que nous avons un fichier appelé
unicode.txt
contenant les deux chaînesΣίσυφος
etΣΊΣΥΦΟΣ
. Avec Python 2:L'Σ caractère a deux minuscules formes, ς et σ, et
.lower()
ne va pas aider à les comparer au cas insensiblement.Cependant, comme de Python 3, tous les trois formes résoudre à ς, et de l'appel de lower() sur les deux chaînes fonctionne correctement:
Donc, si vous vous souciez de bord-cas, comme les trois sigmas en grec, l'utilisation de Python 3.
(Pour référence, Python 2.7.3 et Python 3.3.0b1 sont affichés dans l'interpréteur impressions ci-dessus).
L'article 3.13 de la norme Unicode définit les algorithmes pour sans douille
de correspondance.
X.casefold() == Y.casefold()
en Python 3 met en œuvre le "par défaut sans douille de correspondance" (D144).Casefolding ne permet pas de conserver la normalisation des chaînes dans tous les cas et, par conséquent, la normalisation doit être fait (
'å'
vs'å'
). D145 introduit "canonique sans douille de correspondance":NFD()
est appelé deux fois pour de très rares cas de bord impliquant U+0345 caractère.Exemple:
Il y a également une compatibilité sans douille de correspondance (D146) pour les cas comme
'㎒'
(U+3392) et "identifiant sans douille matching" afin de simplifier et d'optimiser sans douille de correspondance d'identifiants.casefold()
fonction ne permet pas de mettre en œuvre le cas particulier du traitement de majuscule I et parsemée de majuscule I comme décrit dans la Affaire Propriétés de Pliage. Par conséquent, la comparaison peut échouer pour les mots de Turc, les langues qui contiennent ces lettres. Par exemple,canonical_caseless('LİMANI') == canonical_caseless('limanı')
doit retournerTrue
, mais il renvoieFalse
. Actuellement, la seule façon de traiter avec ce Python est d'écrire un casefold wrapper ou externe Unicode bibliothèque, comme PyICU.J'ai vu cette solution ici à l'aide de regex.
Il fonctionne bien avec des accents
Toutefois, il ne fonctionne pas avec les caractères unicode non sensible à la casse. Merci @Rhymoid de remarquer que ma compréhension est qu'il a besoin de symbole exact, pour que l'affaire soit vrai. Le résultat est le suivant:
ß
ne se trouve pas dansSS
avec de la casse de la recherche est la preuve qu'il ne fonctionne pas travailler avec les caractères Unicode tous.L'approche habituelle est pour les chaînes de caractères en majuscules ou en minuscules pour les recherches et les comparaisons. Par exemple:
Comment convertir en minuscules, d'abord? vous pouvez utiliser
string.lower()
.Σίσυφος
etΣΊΣΥΦΟΣ
ne serait pas test équivalent, mais le devrait.C'est une autre regex que j'ai appris à aimer/détester au cours de la dernière semaine, donc en général d'importation (dans ce cas oui) quelque chose qui reflète ce que je ressens!
faire une fonction normale.... demandez l'entrée, puis l'utiliser ....quelque chose = re.compile(r'foo*|spam*', oui.J')...... re.J' (oui.I ci-dessous) est la même que IGNORECASE mais tu ne peux pas faire autant d'erreurs à l'écrire!
Vous alors à la recherche de votre message en utilisant les regex mais honnêtement, qui devrait être de quelques pages dans son propre , mais le point est que foo ou de spam sont reliées ensemble et la casse est ignorée.
Alors si l'un et l'autre sont alors lost_n_found d'affichage, l'un d'eux. si ni puis lost_n_found est égal. Si elle n'est pas égal à aucun retour de la user_input en minuscules à l'aide de "retour lost_n_found.lower()"
Cela vous permet de vous beaucoup plus facilement correspondre à quelque chose des thats va être sensible à la casse. Enfin (NCS) signifie "personne ne se soucie sérieusement...!" ou pas sensibles à la casse....selon
si quelqu'un a des questions à me faire sur ce..
Si vous avez des listes avec des cordes et que vous voulez comparer les chaînes de la liste différente avec de la casse. Voici ma solution.
Après avoir fait cela, vous pouvez faire de la chaîne de comparaison facile.
J'ai utilisé ce pour accomplir quelque chose de plus utile pour comparer deux chaînes de caractères:
Mise à jour: Comme l'a noté gerrit, cette réponse a quelques bugs. C'était il y a des années et je ne me souviens plus de ce que j'ai utilisé pour cela. Je me souviens d'écrire des tests, mais à quoi bon, ils sont désormais!
strings_iequal("1", 1)
. Le résultat seraNone
. Cependant, si je passestrings_iequal("", 0)
, le résultat seraTrue
. Je ne sais pas ce que vous voulez atteindre avec le bloc à l'intérieur de laexcept
-partie.