Какой самый эффективный способ подсчитать все слова в richtextbox? - PullRequest
2 голосов
/ 09 февраля 2010

Я пишу текстовый редактор, и мне нужно указать количество слов в режиме реального времени. Прямо сейчас я использую этот метод расширения:

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

Я установил его так, чтобы счетчик слов выполнялся в тексте richtextbox каждую десятую секунды (если начало выбора отличается от того, которое было в прошлый раз, когда метод запускался). Проблема в том, что при работе с очень длинными файлами количество слов замедляется. Чтобы решить эту проблему, я думаю о том, чтобы подсчет слов выполнялся только в текущем абзаце, каждый раз записывал количество слов и сравнивал его с тем, что было в последний раз при подсчете слов. Это тогда добавило бы разницу между двумя к общему количеству слов. Это может вызвать много сложностей (если пользователь вставляет, если пользователь удаляет абзац и т. Д.) Это логичный способ улучшить количество слов? Или есть что-то, о чем я не знаю, что могло бы сделать его лучше?

EDIT: Будет ли работать подсчет слов в другом потоке? Я не знаю много о потоках, буду исследовать.

Образец текста, который я использовал:

Ответы [ 3 ]

11 голосов
/ 09 февраля 2010

Вы можете сделать более простой подсчет слов на основе пробела:

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

MSDN предоставляет этот пример , должен дать вам точный подсчет слов намного быстрее для больших файлов.

4 голосов
/ 09 февраля 2010

Вы также можете использовать очень простое регулярное выражение, которое ищет хотя бы один символ слова и / или апостроф, чтобы зафиксировать сокращения:

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

Это вернет 2141 совпадений (что на самом деле более правильно, чем Word в этом случае, потому что Word считает одну звездочку как слово в предложении ", ударяя * пальцем").

0 голосов
/ 11 февраля 2010

Ваш метод на самом деле быстрее, чем предлагаемый String.Split метод, почти в три раза быстрее на x86 и более чем в два раза быстрее на x64. Я подозреваю, что JIT портит ваши настройки времени, всегда запускайте ваши микробенчмарки дважды, так как JIT будет занимать подавляющее большинство времени во время вашего первого запуска. И поскольку String.Split был NGEN'd, его не нужно компилировать в нативный код и, следовательно, он будет работать быстрее.

Не говоря уже о том, что он также более точен, String.Split здесь будет насчитывать 7 слов:

test:: это тест

Также имеет смысл, String.Split не выполняет никакой магии, и я был бы очень удивлен, если бы создание массива из множества строк было бы быстрее, чем простая итерация по отдельным символам в строке. Проповедь над строкой, по-видимому, была сильно оптимизирована, поскольку я попробовал unsafe арифметику указателей, и на самом деле она была немного медленнее, чем простая foreach. Я действительно сомневаюсь, что есть какой-то способ сделать это быстрее, кроме умения понять, какие разделы в вашем тексте нуждаются в подсчете слов.

...