Вы пытаетесь использовать неэффективный подход. Стандартный список шаблонов классов не имеет произвольного доступа к его элементам. Каждый новый элемент добавляется в конец списка. Чтобы найти, присутствует ли элемент в списке, его элементы просматриваются последовательно.
Было бы гораздо эффективнее использовать стандартный контейнер std::map
. Более того, в этом контейнере будут упорядочены слова.
Например, вы можете объявить
std::map<std::string, size_t> counters;
Тем не менее, если вы хотите использовать список, функция может выглядеть так, как показано в демонстрационной программе. ниже.
#include <iostream>
#include <string>
#include <list>
#include <vector>
#include <iterator>
#include <algorithm>
struct counter
{
std::string word;
size_t n = 0;
counter() = default;
counter( const std::string &word ): word( word ), n( 1 ){}
};
std::list<counter> list_count( const std::vector<std::string> &text )
{
std::list<counter> word_count;
for ( const auto &s : text )
{
auto it = std::find_if( std::begin( word_count ), std::end( word_count ),
[&s]( const auto &c ) { return c.word == s; } );
if ( it == std::end( word_count ) )
{
word_count.push_back( s );
}
else
{
++it->n;
}
}
return word_count;
}
int main()
{
std::vector<std::string> v { "first", "second", "first" };
auto word_count = list_count( v );
for ( const auto &c : word_count )
{
std::cout << c.word << ": " << c.n << '\n';
}
return 0;
}
Его вывод
first: 2
second: 1
Обратите внимание, что определение счетчика структуры является избыточным. Вместо этого вы можете использовать стандартный класс std :: pair. Вот вам.
#include <iostream>
#include <string>
#include <utility>
#include <list>
#include <vector>
#include <iterator>
#include <algorithm>
std::list<std::pair<std::string, size_t>> list_count( const std::vector<std::string> &text )
{
std::list<std::pair<std::string, size_t>> word_count;
for ( const auto &s : text )
{
auto it = std::find_if( std::begin( word_count ), std::end( word_count ),
[&s]( const auto &p ) { return p.first == s; } );
if ( it == std::end( word_count ) )
{
word_count.emplace_back( s, 1 );
}
else
{
++it->second;
}
}
return word_count;
}
int main()
{
std::vector<std::string> v { "first", "second", "first" };
auto word_count = list_count( v );
for ( const auto &p : word_count )
{
std::cout << p.first << ": " << p.second << '\n';
}
return 0;
}
Если использовать std::map
, то функция будет выглядеть очень просто.
#include <iostream>
#include <string>
#include <vector>
#include <map>
std::map<std::string, size_t> list_count( const std::vector<std::string> &text )
{
std::map<std::string, size_t> word_count;
for ( const auto &s : text )
{
++word_count[s];
}
return word_count;
}
int main()
{
std::vector<std::string> v { "first", "second", "first" };
auto word_count = list_count( v );
for ( const auto &p : word_count )
{
std::cout << p.first << ": " << p.second << '\n';
}
return 0;
}
Использование списка будет эффективным только в том случае, когда вектор строк отсортировано.
Вот демонстрационная программа.
#include <iostream>
#include <string>
#include <list>
#include <vector>
struct counter
{
std::string word;
size_t n = 0;
counter() = default;
counter( const std::string &word ): word( word ), n( 1 ){}
};
std::list<counter> list_count( const std::vector<std::string> &text )
{
std::list<counter> word_count;
for ( const auto &s : text )
{
if ( word_count.empty() || word_count.back().word != s )
{
word_count.push_back( s );
}
else
{
++word_count.back().n;
}
}
return word_count;
}
int main()
{
std::vector<std::string> v { "A", "B", "B", "C", "C", "C", "D", "D", "E" };
auto word_count = list_count( v );
for ( const auto &c : word_count )
{
std::cout << c.word << ": " << c.n << '\n';
}
return 0;
}
Ее вывод
A: 1
B: 2
C: 3
D: 2
E: 1