Question

J'écris un éditeur de texte et je dois fournir un nombre de mots en direct. En ce moment, j'utilise cette méthode d'extension:

 public static int WordCount(this string s)
    {
        s = s.TrimEnd();
        if (String.IsNullOrEmpty(s)) return 0;
        int count = 0;
        bool lastWasWordChar = false;
        foreach (char c in s)
        {
            if (Char.IsLetterOrDigit(c) || c == '_' || c == '\'' || c == '-')
            {
                lastWasWordChar = true;
                continue;
            }
            if (lastWasWordChar)
            {
                lastWasWordChar = false;
                count++;
            }
        }
        if (!lastWasWordChar) count--;
        return count + 1;
    }

Je l'ai réglé pour que le nombre de mots fonctionne sur le texte de Richtextbox chaque dixième de seconde (si le démarrage de sélection est différent de ce qu'il était la dernière fois que la méthode a fonctionné). Le problème est que le nombre de mots devient lent lorsque vous travaillez sur de très longs fichiers. Pour résoudre ce problème, je pense à faire en sorte que le nombre de mots soit uniquement exécuté sur le paragraphe actuel, enregistrant le nombre de mots à chaque fois et le comparant à ce que le nombre de mots était la dernière fois que le nombre de mots a couru. Il ajouterait alors la différence entre les deux au nombre total de mots. Cela entraînerait de nombreuses complications (si l'utilisateur collerait, si l'utilisateur supprime un paragraphe, ect.) Est-ce une façon logique d'améliorer mon nombre de mots? Ou y a-t-il quelque chose que je ne sais pas qui le rendrait meilleur?

Edit: cela fonctionnerait-il pour exécuter le nombre de mots sur un fil différent? Je ne sais pas grand-chose sur le filetage, je ferai des recherches.

Exemple de texte que j'ai utilisé:

Était-ce utile?

La solution

Vous pouvez faire un nombre de mots plus simple basé sur l'espace blanc:

public static int WordCount(this string s)
{
  return s.Split(new char[] {' '}, 
    StringSplitOptions.RemoveEmptyEntries).Length;
}

MSDN fournit cet exemple, devrait vous donner un nombre de mots précis beaucoup plus rapidement sur les fichiers volumineux.

Autres conseils

Vous pouvez également utiliser un regex très simple qui recherche au moins un caractère de mot et / ou une apostrophe pour capturer les contractions:

public static int WordCount(this string s) 
{
    return Regex.Matches(s, @"[\w']+").Count;
}

Cela renverra 2141 correspondances (ce qui est en fait plus correct que le mot dans ce cas car le mot compte le seul astérisque comme un mot dans la phrase "en poignardant un * avec son doigt").

Votre méthode est en fait plus rapide que le proposé String.Split Méthode, près de trois fois plus rapide sur x86 et plus de deux fois plus rapide sur x64 en fait. Je soupçonne que Jit joue avec vos horaires, exécutez toujours vos microbencharques deux fois car JIT occupera le grande majorité du temps pendant votre première course. Et parce que String.Split a été ngen, il n'a pas besoin d'être compilé en code natif et semblera donc être plus rapide.

Sans oublier que c'est aussi plus précis, String.Split comptera 7 mots ici:

Test :: Ceci est un test

Cela a aussi du sens, String.Split n'effectue aucune magie et je serais très surpris si la création d'un tableau de nombreuses chaînes serait plus rapide que d'itérer simplement les caractères individuels de la chaîne. La fortuche d'une chaîne a apparemment été très optimisée pendant que j'ai essayé unsafe Arithmétique du pointeur et c'était en fait un peu plus lent qu'un simple foreach. Je doute vraiment qu'il y ait un moyen de le faire plus rapidement, à part être intelligent sur les sections de votre texte qui ont besoin de comptes de mots.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top