我正在编写文本编辑器,需要提供实时字数。现在我正在使用这种扩展方法:
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;
}
我已将其设置为每十分之一秒在富文本框的文本上运行单词计数(如果选择开始与上次运行该方法时不同)。问题是当处理很长的文件时,字数会变慢。为了解决这个问题,我正在考虑只在当前段落上运行单词count,每次记录单词计数,并将其与上次单词计数运行时的单词计数进行比较。然后它会将两者之间的差异添加到总字数中。 这样做会导致许多复杂情况(如果用户粘贴,如果用户删除了一个段落,等等) 这是改善字数的合理方式吗?或者是否有一些我不知道哪些会使它变得更好?
编辑: 是否可以在不同的线程上运行单词计数?我不太了解线程,会研究。
我使用的示例文字:
答案 0 :(得分:11)
您可以根据空白区域进行更简单的字数统计:
public static int WordCount(this string s)
{
return s.Split(new char[] {' '},
StringSplitOptions.RemoveEmptyEntries).Length;
}
MSDN provides this example,应该可以在大文件上更快地为您提供准确的字数。
答案 1 :(得分:4)
你也可以使用一个非常简单的正则表达式来寻找至少一个单词字符和/或撇号来捕捉收缩:
public static int WordCount(this string s)
{
return Regex.Matches(s, @"[\w']+").Count;
}
这将返回2141个匹配(在这种情况下实际上比Word更正确,因为Word将单个星号计为句子中的一个单词“用手指刺伤*”)。
答案 2 :(得分:0)
您的方法实际上比建议的String.Split
方法更快,在x86上快了近三倍,在x64上快了两倍多。我怀疑JIT正在弄乱你的时间,总是运行你的微基准测试两次,因为JIT将在你第一次运行时占据绝大多数的时间。并且因为String.Split
已被NGEN,所以不需要将其编译为本机代码,因此看起来会更快。
更不用说它也更准确了,String.Split
在这里会算7个字:
测试::这是一个测试
这也是有道理的,String.Split
不执行任何魔法,如果创建一个包含许多字符串的数组比简单地迭代字符串中的单个字符更快,我会感到非常惊讶。当我尝试使用unsafe
指针算法时,对字符串的预告显然已经高度优化,它实际上比简单的foreach
慢一点。我真的怀疑有什么方法可以更快地做到这一点,除了聪明一点,你的文本中哪些部分需要字数。