我正在尝试编写一个程序,它将字符串列表作为输入,并使用字符串名称及其位置创建哈希表。
例:
矢量字{“first”,“second”,“third”,“forth”,“second”};
输出:
第1页
第二个2,5
第三个3
第4页
我遇到两个问题,请在下面的代码评论中找到它们 请告诉我,我做错了什么?
int main()
{
vector<string> words {"first", "second", "third", "forth", "second"};
unordered_map<string, vector<int>> hash_table;
unordered_map<string, vector<int>>::const_iterator hash_it;
int loc = 1;
for(auto n = words.begin(); n != words.end(); ++n){
hash_it = hash_table.find(*n);
if(hash_it == hash_table.end())
hash_table.insert(make_pair(*n, vector<int> (loc)));
else
//hash_it->second.push_back(loc); //Problem 1 - this statement gives error
++loc;
}
for(auto& n:hash_table){
cout<<"Word - "<<n.first<<" Loc -";
vector<int> tmp1 = n.second;
for(auto j = tmp1.begin(); j != tmp1.end(); ++j)
cout<<" "<<*j;
cout<<endl;
}
}
问题2 - 位置值为0
程序输出 -
Word - Four Loc - 0
字 - 第三个地方 - 0
字 - 第二个Loc - 0
Word - 第一个Loc - 0
答案 0 :(得分:3)
你过分复杂化了这个问题,地图上的operator[]
或者特别为这种情况创建了unordered_map:
int loc = 1;
for(auto n = words.begin(); n != words.end(); ++n)
hash_table[*n].push_back( loc++ );
这就是您需要的所有代码。你可以使用范围循环更简单:
int loc = 1;
for(const auto &word: words)
hash_table[word].push_back( loc++ );
答案 1 :(得分:3)
第一个问题是您使用的const_iterator
应该使用iterator
。您无法修改const_iterator
引用的元素。
使用unordered_map<string, vector<int>>::iterator hash_it;
代替unordered_map<string, vector<int>>::const_iterator hash_it;
。更好的是,使用auto
自动推断出要使用的类型。
for (auto n = words.begin(); n != words.end(); ++n) {
auto hash_it = hash_table.find(*n);
// ^^^^ Deduce the correct type
if (hash_it == hash_table.end())
hash_table.insert(make_pair(*n, vector<int>(loc)));
else
hash_it->second.push_back(loc); //No problem
++loc;
}
第二个问题是语句vector<int>(loc)
生成包含loc
值的向量,而不是仅包含loc
的向量。最简单的更改是使用vector<int>(1, loc)
代替,这使得1值等于loc
。
for (auto n = words.begin(); n != words.end(); ++n) {
auto hash_it = hash_table.find(*n);
// ^^^^ Deduce the correct type
if (hash_it == hash_table.end())
hash_table.insert(make_pair(*n, vector<int>(1, loc)));
else
hash_it->second.push_back(loc); //Problem 1 - this statement gives error
++loc;
}
正如其他人所指出的那样,使用operator[]可以省去很多麻烦。请参阅Slava的this answer,了解更简单的方法。
答案 2 :(得分:0)
如果使用unordered_multimap,则可以提高代码效率。那时你不需要一个位置向量。 这是有效的,因为具有相同键的元素保证是连续的顺序。
int main()
{
vector<string> words {"first", "second", "third", "forth", "second"};
unordered_multimap< string, size_t > hash_table;
size_t loc = 0;
for( const auto& word : words )
{
hash_table.insert( make_pair( word, ++loc ) );
}
for( auto i = hash_table.begin(), j = hash_table.begin();
i != hash_table.end();
i = j )
{
cout << "Word - "<< i->first << " Loc -";
// Iterate over all elements with same key
do
{
cout << " " << j->second;
++j;
}
while( j != hash_table.end() && j->first == i->first );
cout << endl;
}
return 0;
}
如果您只想查找特定单词的位置,可以使用unordered_map :: equal_range(),如下所示:
cout << "Locations of 'second':";
auto rng = hash_table.equal_range( "second" );
for( auto i = rng.first; i != rng.second; ++i )
cout << " " << i->second;