76 votes

Comparaison de chaînes de caractères sans tenir compte de la casse

Je voudrais comparer deux variables pour voir si elles sont identiques, mais je veux que cette comparaison soit insensible à la casse.

Par exemple, ceci serait sensible à la casse :

if($var1 == $var2){
   ...
}

Mais je veux que ce soit insensible à la casse, comment dois-je m'y prendre ?

124voto

syrion Points 4280

C'est assez simple, il suffit d'appeler strtolower() sur les deux variables.

Si vous avez besoin de traiter avec Unicode ou des jeux de caractères internationaux, vous pouvez utiliser mb_strtolower() .

Veuillez noter que d'autres réponses suggèrent d'utiliser strcasecmp() -cette fonction ne gère pas les caractères multi-octets, donc les résultats pour toute chaîne UTF-8 seront erronés.

0 votes

Merci, sauriez-vous également comment faire une déclaration WHERE insensible à la casse dans mysql_query() ?

1 votes

En général, je crois que la comparaison de chaînes de caractères MySQL es insensible à la casse. C'est à dire, 'A' = 'a' est vrai. Une référence : dev.mysql.com/doc/refman/5.0/fr/case-sensitivity.html

0 votes

C'est très étrange, car ce n'est pas ce qu'il fait pour moi. J'ai défini la collation sur latin1_swedish_ci.

72voto

Ramon Points 3465

strcasecmp() renvoie 0 si les chaînes sont les mêmes (à part les variations de casse), vous pouvez donc utiliser :

if (strcasecmp($var1, $var2) == 0) {
}

3 votes

N'oubliez pas de tester pour == 0 ; c'est contre-intuitif car il est très tentant d'écrire "if (strcasecmp($var1, $var2)) { ..." mais dans ce cas, 0 signifie égal plutôt que faux-égal comme c'est souvent le cas.

8 votes

strcasecmp() ne traite pas les caractères multi-octets, il ne peut donc pas gérer l'Unicode.

17voto

Beat Points 1237

Si votre chaîne est dans un codage à un seul octet, c'est simple :

if(strtolower($var1) === strtolower($var2))

Si votre chaîne est en UTF-8, vous devez tenir compte de la complexité de l'Unicode : to-lower-case et to-upper-case ne sont pas des fonctions bijectives, c'est-à-dire que si vous avez un caractère minuscule, que vous le transformez en majuscule et que vous le retransformez en minuscule, vous ne vous retrouverez pas forcément avec le même point de code (et il en va de même si vous commencez avec un caractère majuscule).

Par exemple

  • "" ( Latin Capital Letter I with Dot Above, U+0130 ) est un caractère majuscule, avec "i" ( Latin Small Letter I, U+0069 ) comme variante en minuscule - et la variante en majuscule de "i" est "I" ( Latin Capital Letter I, U+0049 ).
  • "" ( Latin Small Letter Dotless I, U+0131 ) est un caractère minuscule, avec "I" ( Latin Capital Letter I, U+0049 ) comme variante en majuscule - et la variante en minuscule de "I" est "i" ( Latin Small Letter I, U+0069 )

Alors mb_strtolower('') === mb_strtolower('i') renvoie faux, même s'ils ont le même caractère majuscule. Si vous voulez vraiment une fonction de comparaison de chaînes de caractères insensible à la casse, vous devez comparer la version en majuscules ET la version en minuscules :

if(mb_strtolower($string1) === mb_strtolower($string2)
  || mb_strtoupper($string1) === mb_strtoupper($string2))

J'ai lancé une requête dans la base de données Unicode à partir de https://codepoints.net ( https://dumps.codepoints.net ) et j'ai trouvé 180 points de code pour lesquels j'ai trouvé un caractère différent en prenant la minuscule de la majuscule du caractère, et 8 points de code pour lesquels j'ai trouvé un caractère différent en prenant la majuscule de la minuscule du caractère.

Mais il y a pire En effet, un même groupe de graphèmes vu par l'utilisateur peut avoir plusieurs façons de le coder : "ä" peut être représenté comme Latin Small Letter a with Diaeresis (U+00E4) ou comme Latin Small Letter A (U+0061) et Combining Diaeresis (U+0308) - et si vous les comparez au niveau de l'octet, cela ne retournera pas vrai !

Mais il existe une solution pour cela dans Unicode : Normalisation ! Il existe quatre formes différentes : NFC, NFD, NFKC, NFKD. Pour la comparaison de chaînes de caractères, NFC et NFD sont équivalents et NFKC et NFKD sont équivalents. Je prendrais NFKC car il est plus court que NFKD, et "" ( Latin Small Ligature ff, U+FB00 ) sera transformé en deux "f" normaux (mais 2 sera aussi étendu à 25 ).

La fonction résultante devient :

function mb_is_string_equal_ci($string1, $string2) {
    $string1_normalized = Normalizer::normalize($string1, Normalizer::FORM_KC);
    $string2_normalized = Normalizer::normalize($string2, Normalizer::FORM_KC);
    return mb_strtolower($string1_normalized) === mb_strtolower($string2_normalized)
            || mb_strtoupper($string1_normalized) === mb_strtoupper($string2_normalized);
}

Veuillez noter :

  • vous avez besoin de la intl pour le Normalisateur
  • vous devriez optimiser cette fonction en vérifiant d'abord s'ils sont égaux^^.
  • vous voudrez peut-être utiliser NFC au lieu de NFKC, car NFKC supprime trop de distinctions de formatage à votre goût
  • vous devez décider par vous-même si vous avez vraiment besoin de toute cette complexité ou si vous préférez une variante plus simple de cette fonction.

2voto

Framework Points 32799
if(strtolower($var1) == strtolower($var2)){
}

1 votes

Bien que je comprenne cette technique et qu'elle soit plutôt basique, ce n'est pas une réponse généreuse ou expliquée. Lorsque les nouveaux chercheurs verront de vieilles réponses uniquement axées sur le code, ils commenceront à penser que c'est une réponse parfaitement acceptable sur Stackoverflow. Veuillez donner l'exemple d'un meilleur comportement en matière de publication de messages, avec l'intention d'éduquer au lieu de balancer une solution et de vous en aller.

0voto

Oswald Points 18625

Utilisez strcasecmp .

1 votes

Comme indiqué dans d'autres réponses, cela ne fonctionne pas pour Unicode.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X