Domanda

Sto scrivendo un editor di testo e la necessità di fornire un numero di parole dal vivo. In questo momento sto usando questo metodo di estensione:

 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;
    }

ho impostato in modo che il numero di parole viene eseguito sul testo del RichTextBox ogni decimo di secondo (se l'inizio di selezione è diverso da quello che era l'ultima volta il metodo ha funzionato). Il problema è che il conteggio delle parole diventa lento quando si lavora su file molto lunghe. Per risolvere questo sto pensando di avere il numero di parole solo eseguito sul paragrafo corrente, registrando il conteggio delle parole ogni volta e nel confronto con ciò che il conteggio delle parole è stata l'ultima volta il conteggio delle parole corse. Sarebbe quindi aggiungere la differenza tra i due per il conteggio totale di parola. In questo modo potrebbe causare molte complicazioni (se le paste utente, se l'utente elimina un paragrafo, ect.) È questo un modo logico per andare su come migliorare il conteggio mia parola? O c'è qualcosa che io non so che renderebbe meglio?

EDIT: Sarebbe lavorare per eseguire il conteggio delle parole su un thread diverso? Non so molto di threading, sarà la ricerca.

TESTO DEL CAMPIONE che ho usato:

È stato utile?

Soluzione

Si potrebbe fare un conteggio delle parole più semplice basata su white-space:

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

MSDN fornisce questo esempio , dovrebbe darvi un conteggio delle parole precise molto più veloce su file di grandi dimensioni.

Altri suggerimenti

Si potrebbe anche usare un semplice Regex che cerca almeno un carattere di parola e / o un apostrofo per catturare le contrazioni:

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

Ciò restituirà 2141 partite (che è in realtà più corretto di Word in questo caso perché Word conta il singolo asterisco come una parola nella frase "a coltellate un * con il dito").

Il vostro metodo è effettivamente più veloce rispetto al metodo String.Split proposto, quasi tre volte più veloce su x86 e più di due volte più veloce su x64 di fatto. Ho il sospetto JIT è pasticciano con i tuoi tempi, eseguire sempre le vostre microbenchmarks il doppio di JIT occuperà la stragrande maggioranza del tempo durante il primo giro. E poiché String.Split è stato NGEN'd, non ha bisogno di essere compilato in codice nativo e pertanto sembra essere più veloce.

Per non parlare è anche più preciso, String.Split conterà 7 parole qui:

  

Test:: questa è una prova

Ha anche senso, String.Split non esegue alcuna magia e sarei molto sorpreso se la creazione di un array di stringhe molti sarebbe più veloce di una semplice iterazione sui singoli caratteri della stringa. Foreaching su una stringa è stato apparentemente altamente ottimizzato, come ho cercato unsafe l'aritmetica dei puntatori e in realtà era un pochino più lenta di una semplice foreach. Ho davvero dubbi non c'è alcun modo per fare questo più veloce, oltre ad essere intelligenti su quali sezioni nel testo hanno bisogno di conteggio delle parole.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top