Python Language Comparaisons de chaînes insensibles à la casse


Exemple

Comparer une chaîne de manière insensible à la casse semble être quelque chose d'anodin, mais ce n'est pas le cas. Cette section ne considère que les chaînes Unicode (la valeur par défaut dans Python 3). Notez que Python 2 peut avoir des faiblesses subtiles par rapport à Python 3 - la gestion unicode ultérieure est beaucoup plus complète.

La première chose à noter est que les conversions de suppression de casse dans Unicode ne sont pas triviales. Il y a du texte pour text.lower() != text.upper().lower() , tel que "ß" :

>>> "ß".lower()
'ß'

>>> "ß".upper().lower()
'ss'

Mais disons que vous vouliez comparer sans "BUSSE" et "Buße" . Heck, vous voulez probablement aussi comparer "BUSSE" et "BUẞE" égaux - c'est la nouvelle forme de capital. La méthode recommandée est d'utiliser le casefold :

Python 3.x 3.3
>>> help(str.casefold)
"""
Help on method_descriptor:

casefold(...)
      S.casefold() -> str
    
     Return a version of S suitable for caseless comparisons.
"""

Ne pas utiliser lower . Si le casefold n'est pas disponible, faire .upper().lower() aide (mais seulement un peu).

Ensuite, vous devriez considérer les accents. Si votre moteur de rendu est bon, vous pensez probablement "ê" == "ê" - mais ce n’est pas le cas:

>>> "ê" == "ê"
False

C'est parce qu'ils sont en fait

>>> import unicodedata

>>> [unicodedata.name(char) for char in "ê"]
['LATIN SMALL LETTER E WITH CIRCUMFLEX']

>>> [unicodedata.name(char) for char in "ê"]
['LATIN SMALL LETTER E', 'COMBINING CIRCUMFLEX ACCENT']

La manière la plus simple de gérer cela est unicodedata.normalize . Vous souhaitez probablement utiliser la normalisation NFKD , mais n'hésitez pas à consulter la documentation. Alors on fait

>>> unicodedata.normalize("NFKD", "ê") == unicodedata.normalize("NFKD", "ê")
True

Pour finir, ceci est exprimé en fonctions:

import unicodedata

def normalize_caseless(text):
    return unicodedata.normalize("NFKD", text.casefold())

def caseless_equal(left, right):
    return normalize_caseless(left) == normalize_caseless(right)