Какой самый эффективный способ подсчитать все слова в RichTextbox?
-
19-09-2019 - |
Вопрос
Я пишу текстовый редактор и должен предоставить живое количество слов. Прямо сейчас я использую этот метод расширения:
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 каждую десятую секунды (если начало выбора отличается от того, что это было в прошлый раз, когда метод запускался). Проблема в том, что количество слов становится медленным при работе над очень длинными файлами. Чтобы решить это, я думаю о том, что слов заполняется только в текущем абзаце, каждый раз записывая подсчет слов и сравнивая его с тем, каким было количество слов в прошлый раз, когда подсчитывается количество слов. Затем это добавило бы разницу между ними к общему количеству слов. Это вызвало бы много осложнений (если пользователь встает, если пользователь удалит абзац, т. Д.) Является ли это логическим способом улучшить количество слов? Или есть что -то, чего я не знаю, что сделает это лучше?
РЕДАКТИРОВАТЬ: Будет ли это работать, чтобы запустить слово в другом потоке? Я не знаю много о потоках, буду исследовать.
Пример текста, который я использовал:
Решение
Вы можете сделать более простое количество слов на основе белого пространства:
public static int WordCount(this string s)
{
return s.Split(new char[] {' '},
StringSplitOptions.RemoveEmptyEntries).Length;
}
MSDN предоставляет этот пример, должно дать вам точное количество слов намного быстрее в больших файлах.
Другие советы
Вы также можете использовать очень простой регуляции, которая ищет хотя бы один характер слова и/или апостроф для захвата сокращений:
public static int WordCount(this string s)
{
return Regex.Matches(s, @"[\w']+").Count;
}
Это вернется 2141 совпадения (что на самом деле более правильное, чем слово в этом случае, потому что Слово считает единственную звездочку как слово в предложении «нанесла удар A * пальцем»).
Ваш метод на самом деле быстрее, чем предложенный String.Split
Метод, почти в три раза быстрее на x86 и более чем в два раза быстрее на X64 на самом деле. Я подозреваю, что JIT возится с вашими временами, всегда запускайте ваши микробенчки в два раза, так как JIT будет занимать подавляющее большинство времени во время вашего первого пробега. И потому что String.Split
Был ngen'd, его не нужно собирать в собственный код и, следовательно, будет казаться быстрее.
Не говоря уже о том, что это также более точное, String.Split
Считает 7 слов здесь:
Тест :: Это тест
Это также имеет смысл, String.Split
Не выполняет никакой магии, и я был бы очень удивлен, если бы создание массива многих строк будет быстрее, чем просто итерация над отдельными символами в строке. Фореация над строкой, очевидно, была очень оптимизирована, когда я пытался unsafe
Указатель арифметика, и это было немного медленнее, чем просто foreach
. Анкет Я действительно сомневаюсь, что есть какой -нибудь способ сделать это быстрее, кроме того, чтобы быть умным в том, какие разделы в вашем тексте нуждаются в подсчете слов.