Combien de fois la lettre « a » apparaît-elle dans le mot « abracadabra » ? Résolvons le problème en C#
Imaginez : vous écrivez un analyseur de logs, analysez un fichier CSV ou vérifiez simplement combien de fois l'utilisateur a saisi le caractère @ dans un email. La tâche « compter le nombre d'occurrences d'un caractère ou d'une sous-chaîne dans une chaîne » est l'une de celles qui se présentent dans un projet sur deux. Sur Stack Overflow, cette question a recueilli des milliers de vues et des dizaines de réponses variées. Pas étonnant : en C#, il existe au moins 5 méthodes différentes, et choisir la bonne peut vous faire gagner des heures de débogage.
Dans cet article, nous allons passer en revue toutes les méthodes populaires – de la boucle classique aux Span<T> et LINQ modernes. Vous découvrirez quelle méthode est la plus rapide, laquelle est la plus lisible, et laquelle il vaut mieux éviter en production. C'est parti !
1. Boucle foreach classique – la méthode de grand-père
La méthode la plus intuitive : on prend la chaîne, on parcourt chaque caractère et on compte les correspondances. Fonctionne toujours, ne nécessite pas de bibliothèques supplémentaires.
string text = "abracadabra";char target = 'a';int count = 0;
foreach (char c in text){ if (c == target) count++;}
Console.WriteLine($"Le caractère '{target}' apparaît {count} fois."); // Sortie : 4Avantages : lisibilité, contrôle sur le processus, possibilité d'ajouter de la logique (par exemple, ignorer la casse).
Inconvénients : ne convient pas pour compter les sous-chaînes (plusieurs caractères consécutifs) – il faudrait écrire une boucle imbriquée.
2. Méthode Count() de LINQ – une ligne pour les caractères
Si vous aimez le code concis et utilisez LINQ, cette option est pour vous. La méthode Count() prend un prédicat et retourne le nombre d'éléments satisfaisant la condition.
using System.Linq;
string text = "Hello, World!";char target = 'l';
int count = text.Count(c => c == target);Console.WriteLine(count); // Sortie : 3Notez que Count() est une méthode d'extension de l'espace de noms System.Linq. Si vous n'avez pas ajouté using System.Linq, le code ne compilera pas.
Pour compter une sous-chaîne, cette méthode ne convient pas directement. Il faudrait d'abord diviser la chaîne ou utiliser des expressions régulières (voir point 5).
3. Span<T> et MemoryExtensions – performances maximales
Si vous travaillez avec de grandes chaînes (mégaoctets de logs) et que chaque milliseconde compte, oubliez LINQ. Utilisez Span<char> et la méthode Count() de MemoryExtensions (disponible à partir de .NET 5+).
using System;
string text = "abracadabra";ReadOnlySpan<char> span = text.AsSpan();int count = span.Count('a');
Console.WriteLine(count); // Sortie : 4Pourquoi est-ce rapide ? Span<T> travaille sur des blocs de mémoire contigus sans allouer de nouveaux objets. La méthode Count() dans MemoryExtensions est optimisée pour les instructions SIMD – elle traite 16 à 32 caractères par cycle processeur.
Pour les sous-chaînes, il existe aussi une solution :
int count = span.Count("ra"); // compte les occurrences de la sous-chaîne "ra"Console.WriteLine(count); // Sortie : 2 ("abracadabra" contient "ra" deux fois)Important : cette méthode est sensible à la casse. Si vous devez ignorer la casse, convertissez d'abord la chaîne en une seule casse ou utilisez span.Count("ra", StringComparison.OrdinalIgnoreCase).
4. Méthode Split – une astuce pour les sous-chaînes
Une méthode ancienne mais efficace : diviser la chaîne par la sous-chaîne recherchée et compter le nombre de parties moins un.
string text = "un, deux, trois, un, quatre";string target = "un";
int count = text.Split(target, StringSplitOptions.None).Length - 1;Console.WriteLine(count); // Sortie : 2Comment ça marche : Split