C ++ unordered_map插入到vector中

时间:2017-02-15 20:47:27

标签: c++ vector unordered-map

我正在尝试编写一个程序,它将字符串列表作为输入,并使用字符串名称及其位置创建哈希表。

例:
矢量字{“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

3 个答案:

答案 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;