Lors de comparaisons non sensibles à la casse, est-il plus efficace de convertir la chaîne en majuscules ou en minuscules? Est-ce même important?
Il est suggéré dans ce SO post que C # est plus efficace avec ToUpper parce que "Microsoft l'a optimisé de cette façon." Mais j'ai également lu ce argument que la conversion de ToLower vs. ToUpper dépend de ce que vos chaînes contiennent le plus, et que les chaînes contiennent généralement plus de caractères minuscules, ce qui rend ToLower plus efficace.
En particulier, je voudrais savoir:
La conversion en majuscules ou en minuscules afin de faire des comparaisons non sensibles à la casse est incorrecte en raison des caractéristiques "intéressantes" de certaines cultures, en particulier la Turquie. À la place, utilisez un StringComparer avec les options appropriées.
MSDN a quelques grandes lignes directrices sur la gestion des chaînes. Vous pouvez également vérifier que votre code passe le test de la Turquie .
EDIT: Notez le commentaire de Neil autour de ordinal comparaisons insensibles à la casse. Tout ce domaine est assez trouble :(
De Microsoft sur MSDN:
Meilleures pratiques pour l'utilisation de chaînes dans le .NET Framework
Recommandations pour l'utilisation des chaînes
- Utilisez la méthode String.ToUpperInvariant au lieu de la méthode String.ToLowerInvariant lorsque vous normalisez les chaînes à des fins de comparaison.
Pourquoi? De Microsoft :
Normaliser les chaînes en majuscules
Il y a un petit groupe de caractères qui, lorsqu'ils sont convertis en minuscules, ne peuvent pas faire un aller-retour.
Quel est l'exemple d'un tel personnage qui ne peut pas faire un aller-retour?
ϱ, Ρ , ρ
C'est pourquoi, si vous voulez faire des comparaisons insensibles à la casse, vous convertissez les chaînes en majuscules et non en minuscules.
Selon MSDN il est plus efficace de passer les chaînes et de dire à la comparaison d'ignorer la casse:
String.Compare (strA, strB, StringComparison.OrdinalIgnoreCase) est équivalent à ( mais plus rapide que ) appel
String.Compare (ToUpperInvariant (strA), ToUpperInvariant (strB), StringComparison.Ordinal).
Ces comparaisons sont encore très rapides.
Bien sûr, si vous comparez une chaîne encore et encore, cela peut ne pas tenir.
Basé sur des chaînes ayant généralement plus d'entrées en minuscules, ToLower devrait théoriquement être plus rapide (beaucoup de comparaisons, mais peu d'affectations).
En C, ou lorsque vous utilisez des éléments accessibles individuellement de chaque chaîne (tels que les chaînes C ou le type de chaîne STL en C++), il s'agit en fait d'une comparaison d'octets - donc la comparaison de UPPER
n'est pas différente de lower
.
Si vous étiez sournois et chargiez vos chaînes dans des tableaux long
à la place, vous obtiendriez une comparaison très rapide sur la chaîne entière car elle pourrait comparer 4 octets à la fois. Cependant, le temps de chargement peut ne pas en valoir la peine.
Pourquoi avez-vous besoin de savoir lequel est le plus rapide? À moins que vous ne fassiez une charge métrique de comparaisons, une exécution de quelques cycles plus rapidement n'est pas pertinente pour la vitesse d'exécution globale et sonne comme une optimisation prématurée :)
Microsoft a optimisé ToUpperInvariant()
, pas ToUpper()
. La différence est que l'invariant est plus respectueux de la culture. Si vous devez effectuer des comparaisons non sensibles à la casse sur des chaînes qui peuvent varier dans la culture, utilisez Invariant, sinon les performances de la conversion invariante ne devraient pas avoir d'importance.
Je ne peux pas dire cependant si ToUpper () ou ToLower () est plus rapide. Je ne l'ai jamais essayé car je n'ai jamais eu une situation où les performances étaient si importantes.
Si vous effectuez une comparaison de chaînes en C #, il est beaucoup plus rapide d'utiliser .Equals () au lieu de convertir les deux chaînes en majuscules ou en minuscules. Un autre gros avantage de l'utilisation de .Equals () est que plus de mémoire n'est pas allouée pour les 2 nouvelles chaînes majuscules/minuscules.
Cela ne devrait vraiment jamais avoir d'importance. Avec ASCII caractères, cela n'a vraiment pas d'importance - ce ne sont que quelques comparaisons et un peu flip pour l'une ou l'autre direction. Unicode pourrait être un peu plus compliqué, car il y a des caractères qui changent la casse dans façons étranges, mais il ne devrait vraiment pas y avoir de différence à moins que votre texte ne soit plein de ces caractères spéciaux.
Si vous le faites correctement, il devrait y avoir un petit avantage de vitesse insignifiant si vous convertissez en minuscules, mais cela, comme beaucoup l'ont laissé entendre, dépend de la culture et n'est pas hérité de la fonction mais des chaînes que vous convertissez (beaucoup de lettres minuscules) signifie peu d'affectations à la mémoire) - la conversion en majuscules est plus rapide si vous avez une chaîne avec beaucoup de lettres majuscules.
Ça dépend. Comme indiqué ci-dessus, tout simplement ASCII, son identique. Dans .NET, lisez et utilisez String.Compare c'est correct pour les choses i18n (cultures de langues et unicode). Si vous savez quelque chose sur la probabilité de l'entrée, utilisez le cas le plus courant.
N'oubliez pas que si vous effectuez plusieurs comparaisons de chaînes, la longueur est un excellent premier discriminateur.