I am writing a program that counts the number of words in a text file which is already in lowercase and separated by spaces. I want to use a dictionary and only count the word IF it’s within the dictionary. The problem is the dictionary is quite large (~100,000 words) and each text document has also ~50,000 words. As such, the codes that I wrote below gets very slow (takes about 15 sec to process one document on a quad i7 machine). I’m wondering if there’s something wrong with my coding and if the efficiency of the program can be improved. Thanks so much for your help. Code below:
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;
}
You can vastly improve performance by reading the text file one line at a time instead of building an enormous string.
You can call
Do not call
ReadAllLines; it will need to build an enormous array.Your first
Selectcall is utterly useless.Your
Containscall will loop through the entire dictionary for each word in the file.Thus, the
Wherecall is an O(n2) operation.Change
keywordsto aHashSet<string>.Since HashSets can be searched in constant time, the
Wherecall will become an O(n) operation, which is much better.Your second
Selectcall can be combined with theGroupBy, which will cut a large number of object allocations:Dictionaries are intrisically unordered, so your
OrderBycall is a useless waste of time.