У меня есть массив слов, и у меня есть текстовый файл. То, что я хочу сделать, это использовать массив слов и искать в текстовом файле, подсчитать, сколько раз каждое слово в массиве появляется в текстовом файле.
Я думал об использовании For Loop, но это просто дало мне общее количество слов, а не отдельные слова для каждого. Я не могу поместить текстовый файл в массив, так как в текстовом файле около 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;
Прежде чем беспокоиться об эффективности, вам следует побеспокоиться о подходе. Вы не используете логические структуры данных. Вместо 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 (вполне вероятно, всегда) реализован как хэш-карта, и std :: map реализован (вполне вероятно, всегда) с использованием сбалансированного бинарного дерева в качестве вспомогательной структуры.
Настроить 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
и выберите тот, который работает лучше всего.
Имея только 8 значений для сравнения, вы, скорее всего, сможете найти лучший алгоритм хеширования, чем в std. Он может состоять только из первых двух символов, или последнего символа, или длины строки:
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.
Все остальные ответы здесь являются очень хорошими предложениями. Одна небольшая оптимизация, которую вы можете сделать, это использовать еще в вашем существующем коде.
if (inWord == testwords[0])
{
count1++;
}
if (inWord == testwords[1])
{
count2++;
}
может быть заменено
if (inWord == testwords[0])
{
count1++;
}
else if (inWord == testwords[1])
{
count2++;
}
Концепция заключается в том, что если в слове соответствует элементу 0, вряд ли он соответствует любому из других элементов.
В любом случае Профайлеры ты друг?