我有一个单词数组,我有一个文本文件。我想要做的是使用单词数组并搜索文本文件,计算数组中每个单词出现在文本文件中的次数。
我曾考虑过使用For循环,但这只是给了我字数的总和,而不是每个单词的单个字数。我不能将文本文件放入数组中,因为文本文件中有大约40000个单词。
计数后,我想将每个计数除以一个称为'scale'的整数值。然后按新计数编号多次填充字符串。
所以我现在正在做,如下所示。无论如何我可以提高效率吗?
非常感谢任何帮助。
单词数组= testwords。
文件名= testF。
inWord =文件中的每个单词。
while(testF >> inWord)
{if (inWord == testwords[0]){
count1++;
}
if (inWord == testwords[1]){
count2++;
}
if (inWord == testwords[2]){
count3++;
}
if (inWord == testwords[3]){
count4++;
}
if (inWord == testwords[4]){
count5++;
}
if (inWord == testwords[5]){
count6++;
}
if (inWord == testwords[6]){
count7++;
}
if (inWord == testwords[7]){
count8++;
}
}
cout << testwords[0] << " " << count1 << " " << s1.append(count1/scale, '*') << endl;
cout << testwords[1] << " " << count2 << " " << s2.append(count2/scale, '*') << endl;
cout << testwords[2] << " " << count3 << " " << s3.append(count3/scale, '*') << endl;
cout << testwords[3] << " " << count4 << " " << s4.append(count4/scale, '*') << endl;
cout << testwords[4] << " " << count5 << " " << s5.append(count5/scale, '*') << endl;
cout << testwords[5] << " " << count6 << " " << s6.append(count6/scale, '*') << endl;
cout << testwords[6] << " " << count7 << " " << s7.append(count7/scale, '*') << endl;
cout << testwords[7] << " " << count8 << " " << s8.append(count8/scale, '*') << endl;
答案 0 :(得分:4)
在担心效率之前,您应该担心接近问题。您没有使用逻辑数据结构。不要有8个单独的计数,而是保留一系列计数。或者更好的是,保留一张单词地图 - &gt;计数。
幸运的是,在这种情况下,更清晰的代码将对应更快的执行速度。
特别要使用std::map<std::string, size_t>
。
或者,如果您使用的是C ++ 11,则可以使用std :: unordered_map来获得更好的性能。
假设您正在阅读cin
中的单词:
std::map<std::string, size_t> counts;
std::string word;
while (std::cin >> word) {
++counts[word];
}
for (std::map<std::string, size_t::const_iterator it = counts.begin(),
end = counts.end(); it != end; ++it) {
std::cout << "The word '" << it->first << " appeared "
<< it->second << " times" << std::endl;
}
对于std :: map。
对于std :: unordered_map,
对于它的价值,std :: unordered_map(很可能总是)实现为hash map,并且使用平衡二叉树作为后端结构来实现std :: map(非常值得一提)。 / p>
答案 1 :(得分:1)
设置std::map<std::string, unsigned long long>
,逐字扫描文档,并为每个单词递增计数器:
std::map<std::string, unsigned long long> wordMap;
std::string word; // read words into this string
...
wordMap[word]++; // increase counter each time a word is found. First call will insert 0.
然后你可以遍历你的单词数组,检查地图中的条目:
for (unsigned int i = 0; i < nWords; ++i)
{
std::cout << "Word " << testWords[i] << " was found " << wordMap[testWords[i]] << " times\n";
}
每次找到新词时,myMap[word]
都会插入一个键值对word : 0
。
如果你有c ++ 11,你可以尝试使用std::unordered_map
并选择效果最好的那个。
答案 2 :(得分:0)
只需比较8个值,您很可能找到比std更好的哈希算法。它可能只包含前两个字符,或最后一个字符,或者字符串lenght:
while (std::cin >> word) {
int i=my_hash(word);
if (word==my_sparse_hash_table[i].word) my_sparse_hash_table[i].count++;
}
只需使用您的方法:
while (std::cin >> word) {
for (int i=0;i<N;i++)
if (word == myTable[i].word) { myTable[i].count++; break; }
} // earlies break out of the loop
微优化包括将找到的条目移动到数组myTable的开头。
答案 3 :(得分:0)
这里的所有其他答案都是非常好的建议。您可以进行的一项小规模优化是在现有代码中使用 else 。
if (inWord == testwords[0])
{
count1++;
}
if (inWord == testwords[1])
{
count2++;
}
可以替换为
if (inWord == testwords[0])
{
count1++;
}
else if (inWord == testwords[1])
{
count2++;
}
概念是,如果 inWord 与元素0匹配,则不太可能匹配任何其他元素。
无论如何,Profilers是你的朋友。