提高这段文本处理代码的效率

3
我正在编写一个程序,用于计算一个已经转换成小写并由空格分隔的文本文件中单词的数量。我想使用一个字典,只有当单词在字典中时才进行计数。问题是字典相当大(约100,000个单词),而每个文本文档也有约50,000个单词。因此,我下面编写的代码会变得非常慢(在四核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;

        } 

你为什么要制作一个字典? - SLaks
4个回答

7

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

您可以调用

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

请勿调用ReadAllLines方法,因为它需要构建一个巨大的数组。
你的第一个Select调用完全没有用处。
对于文件中的每个单词,你的Contains调用都会遍历整个字典。因此,Where调用是一个O(n2)操作。
keywords更改为HashSet<string>。由于哈希集可以在常数时间内搜索,Where调用将变成O(n)操作,这要好得多。
你的第二个Select调用可以与GroupBy合并,这将减少大量对象分配:
 .GroupBy(c => c, (word, set) => new { word, count = set.Count() })

字典本质上是无序的,所以您的OrderBy调用是徒劳无功的浪费时间。


如果能描述一下为什么这会加速事情,我会给你一个+1。 - Nick Larsen
一定要喜欢Linq,它使得添加O(n)变得轻松愉快。 - Brook
@SLaks,感谢您的贡献。强调一下,除了 HashSet 的更改之外,其他更改对于大规模的 n 来说并没有太大的影响。 - Nick Larsen
@SLaks EnumerateLines在哪里?我知道ReadLines在.NET 4.0中可用,它允许在整个集合返回之前进行枚举,但不熟悉EnumerateLines。 - Aaron McIver
@Aaron:编辑:抱歉,我是指ReadLines - SLaks
显示剩余2条评论

1

根据我看到的,你的所有代码都可以被替换为

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

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

他想要一个逐词的字典。 - SLaks
1
@SLaks提供的代码中,他返回单词计数,并且根本没有使用(返回)字典。我哪里错了? - The Smallest

1

既然你在运行四核处理器,那么你至少可以在其中加入一个AsParallel()


0

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

如果你想变得非常高级,可以使用一些PLINQ来利用多个线程,但在采取这种方法之前,请确保你已经优化了单线程性能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接