提高此文本处理代码的效率

时间:2010-12-27 14:53:17

标签: c# text

我正在编写一个程序来计算文本文件中的单词数,该单词已经是小写并用空格分隔。我想使用字典,只计算字典中的单词IF。问题是字典很大(~100万字),每个文本文件也有~5,000字。因此,我在下面写的代码变得非常慢(在quad i7机器上处理一个文档大约需要15秒)。我想知道我的编码是否有问题,以及程序的效率是否可以提高。非常感谢你的帮助。代码如下:

public static string WordCount(string countInput)
        {
            string[] keywords = ReadDic(); /* read dictionary txt file*/

            /*then reads the main text file*/
            Dictionary<string, int> dict = ReadFile(countInput).Split(' ')
                .Select(c => c)
                .Where(c => keywords.Contains(c))
                .GroupBy(c => c)
                .Select(g => new { word = g.Key, count = g.Count() })
                .OrderBy(g => g.word)
                .ToDictionary(d => d.word, d => d.count);

            int s = dict.Sum(e => e.Value);
            string k = s.ToString();
            return k;

        } 

4 个答案:

答案 0 :(得分:7)

通过一次读取一行文本文件而不是构建一个巨大的字符串,可以大大提高性能。

你可以打电话

File.ReadLines(path).SelectMany(s => s.Split(' '))

不要致电ReadAllLines;它需要建立一个巨大的阵列。


您的第一次Select来电完全无法使用


您的Contains来电将循环播放文件中每个字词的整个词典 因此,Where调用是O(n 2 )操作。

keywords更改为HashSet<string> 由于可以在恒定时间内搜索HashSet,Where调用将成为O(n)操作,这样做要好得多。


您的第二个Select来电可以与GroupBy合并,这会削减大量的对象分配:

 .GroupBy(c => c, (word, set) => new { word, count = set.Count() })

词典本质上是无序的,因此您的OrderBy电话是无用的浪费时间。

答案 1 :(得分:1)

我可以看到所有代码都可以替换为

return ReadFile(countInput).Split(' ').Count(c => keywords.Contains(c));

而且,正如 SLaks 所说,HashSet - 会提高性能 还有一个改进:如果你在循环中调用这个代码,你不应该在每次迭代时读取ReadDic() - 加载一次并作为参数传递。

答案 2 :(得分:1)

由于你正在运行四核,你至少可以在那里投入一个AsParallel()

答案 3 :(得分:0)

尝试将string[] keywords更改为HashSet<string> keywords。您对“Contains”的调用本质上是一个循环,它比使用散列键查找要慢得多。

如果你想获得真正的花哨,可以使用一些PLINQ来使用多个线程,但我会确保你在走这条路线之前优化了你的单线程性能。