2

我有一个单词数组,我有一个文本文件。我想要做的是使用单词数组并搜索文本文件,计算数组中每个单词出现在文本文件中的次数。

我曾考虑过使用 For 循环,但这只是给了我总字数,而不是每个字数。我无法将文本文件放入数组中,因为文本文件中有大约 40000 个单词。

计数后,我想将每个计数除以一个称为“比例”的整数值。然后用新的计数乘以一个字符串。

所以我目前正在这样做,如下所示。无论如何我可以提高效率吗?

任何帮助是极大的赞赏。

单词数组 = 测试词。

文件名 = 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;
4

4 回答 4

4

在担心效率之前,您应该担心方法。您没有使用逻辑数据结构。不要有 8 个单独的计数,而是保留一个计数数组。或者更好的是,保留单词图 -> 计数。

幸运的是,在这种情况下,更简洁的代码将对应于更快的执行速度。

特别是,使用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 使用平衡二叉树作为支持结构来实现(几乎总是)。

于 2012-11-17T12:21:10.000 回答
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,你可以尝试使用 anstd::unordered_map并选择性能最好的。

于 2012-11-17T12:21:04.227 回答
0

只需比较 8 个值,您很可能会找到比 std.h 更好的哈希算法。它可能只包含前两个字符,或最后一个字符,或字符串长度:

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 的开头。

于 2012-11-17T12:34:58.750 回答
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都是你的朋友。

于 2012-11-17T13:09:05.910 回答