Frage

Ich schreibe einen Texteditor und muss eine Live -Wortzahl bereitstellen. Im Moment verwende ich diese Erweiterungsmethode:

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

Ich habe es so festgelegt, dass die Wortzahl in jedem Zehntel Sekunde auf dem Text der RichTextBox ausgeführt wird (wenn sich die Auswahlstart von dem, was die Methode letztes war, unterscheidet, unterscheidet sich die Methode). Das Problem ist, dass die Wortanzahl bei der Arbeit an sehr langen Dateien langsam wird. Um dies zu lösen, denke ich darüber nach, dass die Wortzahl nur im aktuellen Absatz ausgeführt wird, die Wortzahl jedes Mal aufzeichnet und sie mit dem verglichen, was die Wortanzahl das letzte Mal war, als die Wortzahl lief. Es würde dann die Differenz zwischen den beiden zur Gesamtwortzahl hinzufügen. Dies würde viele Komplikationen verursachen (wenn der Benutzer festlegt, wenn der Benutzer einen Absatz löscht, ect.) Ist dies eine logische Möglichkeit, meine Wortanzahl zu verbessern? Oder gibt es etwas, von dem ich nicht weiß, was es besser machen würde?

Bearbeiten: Würde es funktionieren, die Wortanzahl auf einem anderen Thread auszuführen? Ich weiß nicht viel über das Threading, werde recherchieren.

Beispieltext, den ich verwendet habe:

War es hilfreich?

Lösung

Sie können eine einfachere Wortanzahl basierend auf dem weißen Raum durchführen:

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

MSDN liefert dieses Beispiel, sollten Sie in großen Dateien eine genaue Wortanzahl viel schneller geben.

Andere Tipps

Sie können auch eine sehr einfache Regex verwenden, die nach mindestens einem Wortcharakter und/oder einem Apostroph sucht, um die Kontraktionen zu erfassen:

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

Dies gibt 2141 Übereinstimmungen zurück (was in diesem Fall tatsächlich korrekter als Wort ist, da das Wort das einzelne Sternchen als Wort im Satz "durch Erstechen a * mit ihrem Finger" zählt).

Ihre Methode ist tatsächlich schneller als die vorgeschlagene String.Split Methode, fast dreimal schneller auf x86 und mehr als zweimal schneller auf X64. Ich vermute, dass JIT mit Ihren Zeitungen herumspielt, immer Ihre Mikrobenchmarks zweimal durchführen, da JIT das besetzt große Mehrheit von der Zeit während Ihres ersten Laufs. Und weil String.Split Wurde nicht gener, es muss nicht mit nativem Code zusammengestellt werden und scheint daher schneller zu sein.

Ganz zu schweigen davon, dass es auch genauer ist, String.Split wird hier 7 Wörter zählen:

Test :: Dies ist ein Test

Es macht auch Sinn, String.Split führt keine Magie durch und ich wäre sehr überrascht, wenn die Erstellung einer Reihe vieler Saiten schneller wäre, als nur die einzelnen Charaktere in der Saite zu iterieren. Nach einer Saite wurde es anscheinend sehr optimiert, wie ich es versucht habe unsafe Zeigerarithmetik und es war tatsächlich etwas langsamer als ein einfacher foreach. Ich bezweifle wirklich, dass es eine Möglichkeit gibt, dies schneller zu tun, außer klug darüber zu sein, welche Abschnitte in Ihrem Text Wortzählungen benötigen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top