【问题标题】:What is the most efficient way to count all of the words in a richtextbox?计算富文本框中所有单词的最有效方法是什么?
【发布时间】:2011-01-14 15:10:29
【问题描述】:

我正在编写一个文本编辑器,需要提供实时字数统计。现在我正在使用这个扩展方法:

 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 的文本运行一次字数统计(如果选择开始与上次运行该方法时的开始不同)。问题是在处理非常长的文件时字数会变慢。为了解决这个问题,我正在考虑只在当前段落上运行字数,每次记录字数并将其与上次运行字数时的字数进行比较。然后它将两者之间的差异添加到总字数中。 这样做会导致很多并发症(如果用户粘贴,如果用户删除段落等) 这是提高我的字数的合乎逻辑的方法吗?或者有什么我不知道的东西会让它变得更好吗?

编辑: 在不同的线程上运行字数统计会起作用吗?我对线程了解不多,会研究一下。

我使用的示例文本:

【问题讨论】:

    标签: c# wpf performance richtextbox word-count


    【解决方案1】:

    您的方法实际上比建议的 String.Split 方法快,在 x86 上快了近三倍,实际上在 x64 上快了两倍多。我怀疑 JIT 弄乱了你的时间,总是运行你的微基准测试两次,因为 JIT 在你第一次运行时会占据绝大多数的时间。而且因为String.Split 已经过NGEN,它不需要编译为本机代码,因此看起来会更快。

    别说还更准确,String.Split 会在这里算 7 个字:

    测试 :     : 这是一个测试

    这也是有道理的,String.Split 不会执行任何魔法,如果创建多个字符串的数组比简单地迭代字符串中的单个字符更快,我会感到非常惊讶。在我尝试unsafe 指针算法时,对字符串的遍历显然已经高度优化,它实际上比简单的foreach 慢了一点。我真的怀疑有什么方法可以更快地做到这一点,除了聪明地知道你的文本中的哪些部分需要字数统计。

    【讨论】:

      【解决方案2】:

      您可以根据空格进行更简单的字数统计:

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

      MSDN provides this example,应该可以更快地为您提供大文件的准确字数统计。

      【讨论】:

      • 感谢您的回复,但这种方法不够准确。刚才我在一个文档中测试了我原始帖子中的方法和这篇文章中的方法,根据 Microsoft Word,该文档有 2,142 个字长。这篇文章中的方法数为 2,165,我原帖中的方法数为 2,141。
      • @highone - 发布该示例文本块......我会看看有什么区别,我们可以稍微调整一下。
      • 我不得不发布文本作为答案,因为它太大而无法放入评论中。我是 stackoverflow 的新手,不确定是否应该将其发布为社区 wiki。
      • @highone - 我更新了答案,我用这种方法得到了 2,142...看看它是否适合你。
      • @highone - 我做了一些基准测试,这种方法的速度至少是任何其他方法的两倍。如果速度是您的主要要求,那么这就是您要使用的方法... +1
      【解决方案3】:

      您还可以使用一个非常简单的正则表达式来查找至少一个单词字符和/或撇号来捕获缩写:

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

      这将返回 2141 个匹配项(在这种情况下实际上比 Word 更正确,因为 Word 将单个星号计为句子中的一个单词“通过用手指戳 *”)。

      【讨论】:

      • 不幸的是,正则表达式比我目前使用的方法慢得多。
      • @highone - 我在尼克的回答中指出了这一点。你有一个权衡,你想牺牲一些速度来获得准确性吗?正如我上面提到的,当涉及到某些标点符号时,即使是 Word 也是不正确的。这一切都取决于你想要什么。拆分始终是最快的方法,除非它是一个新文档,并且您在用户键入时跟踪字数。
      • 在用户键入时跟踪字数到底是什么意思?
      猜你喜欢
      • 2011-01-26
      • 1970-01-01
      • 2011-07-13
      • 1970-01-01
      • 2021-03-18
      • 1970-01-01
      • 2012-08-14
      • 1970-01-01
      • 2013-01-23
      相关资源
      最近更新 更多