Kaitlin
Kaitlin

Reputation: 51

STL Unordered Map- inserting into a vector

I am not too familiar with the STL's unordered map and I'm having trouble inserting elements into it.

So I have an unordered map where the key is a string and the mapped value is a vector of integers. I have it declared as:

              unordered_map<string, vector<int> > categorySearch;

How would I go about inserting elements into this map. I am currently doing

       categorySearch.insert(make_pair("hello", categorySearch["hello"].push_back(5)));

This is clearly giving me compiler errors. How do I use insert for the vector portion of the map.

Here is the compiler error I am getting:

logData.h: In member function ‘void LogData::addEntry(Log)’:
logData.h:23:68: error: no match for ‘operator[]’ (operand types are ‘std::unordered_map<std::basic_string<char>, std::vector<int> >’ and ‘<unresolved overloaded function type>’)
categorySearch.insert(make_pair(add.getCategory(), categorySearch[add.getCategory].push_back(data.size()-1)));
                                                                ^
logData.h:23:68: note: candidates are:
In file included from /usr/um/gcc-4.8.2/include/c++/4.8.2/unordered_map:48:0,
             from logData.h:2,
             from logman.cpp:5:
/usr/um/gcc-4.8.2/include/c++/4.8.2/bits/unordered_map.h:595:7: note: std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type& std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](const key_type&) [with _Key = std::basic_string<char>; _Tp = std::vector<int>; _Hash = std::hash<std::basic_string<char> >; _Pred = std::equal_to<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::vector<int> > >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type = std::vector<int>; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type = std::basic_string<char>]
   operator[](const key_type& __k)
   ^
/usr/um/gcc-4.8.2/include/c++/4.8.2/bits/unordered_map.h:595:7: note:   no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘const key_type& {aka const std::basic_string<char>&}’
/usr/um/gcc-4.8.2/include/c++/4.8.2/bits/unordered_map.h:599:7: note: std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type& std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type&&) [with _Key = std::basic_string<char>; _Tp = std::vector<int>; _Hash = std::hash<std::basic_string<char> >; _Pred = std::equal_to<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::vector<int> > >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type = std::vector<int>; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type = std::basic_string<char>]
   operator[](key_type&& __k)
   ^
/usr/um/gcc-4.8.2/include/c++/4.8.2/bits/unordered_map.h:599:7: note:   no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘std::unordered_map<std::basic_string<char>, std::vector<int> >::key_type&& {aka std::basic_string<char>&&}’
make: *** [logman.o] Error 1

Thanks.

Upvotes: 3

Views: 9724

Answers (2)

Jerry Coffin
Jerry Coffin

Reputation: 490653

I think I'd take one of two approaches. The first possibility would be to use the map's operator[], so the code looked like:

category_search["hello"].push_back(5);

The other obvious possibility would be to recognize that what you're creating (each key having multiple mapped values) is equivalent to what an unordered_multimap provides, so you could just use:

std::unordered_multimap<std::string, int> category_search;

category_search.emplace("hello", 5);

Note that I've also used emplace to simplify the code (and as a bonus, probably run a little faster as well).

And yes, both of these support multiple values, so you could add:

category_search["hello"].push_back(10);

... or:

category_search.emplace("hello", 10);

...to the unordered_map/unordered_multimap respectively to also associate the value 10 with the key hello.

In the case of the unordered_multimap, you'd retrieve the set of values associated with a particular key using equal_range, like:

auto p = category_search.equal_range("hello");

This will put the beginning of the range in p.first and the end in p.second.

Upvotes: 3

PaulMcKenzie
PaulMcKenzie

Reputation: 35455

The second in the pair is a vector<int>, so you construct a vector with 1 element initialized with 5 instead of push_back.

 categorySearch.insert(make_pair("hello", std::vector<int>(1,5)));

Live example: http://ideone.com/JlMUuN

If the item already exists, use the return value that unordered_map::insert gives you, which is a std::pair consisting of the iterator and a bool denoting the success of the insertion:

#include <vector>
#include <unordered_map>
#include <string>
#include <iostream>

using namespace std;
int main()
{
    typedef unordered_map<string, vector<int>> CMap;
    CMap category_map;
    category_map.insert(make_pair("hello", std::vector<int>(1, 5)));
    auto pr = category_map.insert(make_pair("hello", std::vector<int>(1, 5)));
    if (!pr.second)
        pr.first->second.push_back(10);
    cout << pr.first->second.size(); 
}

Live Example: http://ideone.com/svEqcD

You will see that the map entry for "hello" has now 2 items in the vector, since the second call to insert failed due to item previously existing.

See here: http://en.cppreference.com/w/cpp/container/unordered_map/insert

Upvotes: 1

Related Questions