Search code examples
c++iteratorc++17stdvectorstdmap

How to print std::map<int, std::vector<int>>?


Following is my code for creating a map<int, vector<int>> and printing:

//map<int, vector>
map<int, vector<int>> int_vector;
vector<int> vec;
vec.push_back(2);
vec.push_back(5);
vec.push_back(7);

int_vector.insert(make_pair(1, vec));

vec.clear();
if (!vec.empty())
{
    cout << "error:";
    return -1;
}
vec.push_back(1);
vec.push_back(3);
vec.push_back(6);
int_vector.insert(make_pair(2, vec));

//print the map
map<int, vector<int>>::iterator itr;
cout << "\n The map int_vector is: \n";
for (itr2 = int_vector.begin(); itr != int_vector.end(); ++itr)
{
    cout << "\t " << itr->first << "\t" << itr->second << "\n";
}
cout << endl;

The printing part does not work because of the

error: C2678: binary '<<': no operator found which takes a left-hand operand of type 
'std::basic_ostream<char,std::char_traits<char>>' (or there is no acceptable conversion)

Solution

  • The value of your maps(std::map<int, std::vector<int>>) is a vector of int s and there is no operator<< defined for printing a std::vector<int> in the standard. You need to iterate through the vector(i.e. values of the map) to print the elements.

    for (itr = int_vector.begin(); itr != int_vector.end(); ++itr)
    //     ^^ --> also you had a typo here: itr not itr2     
    {
        cout << "\t " << itr->first << "\t";
        for(const auto element: itr->second) std::cout << element << " ";
        std::cout << '\n';
    }
    

    That being said, if you have access to C++11, you could use range-based for loops. And in C++17, you could do more intuitively structured binding declarations for the key-value of the map:

    for (auto const& [key, Vec] : int_vector)
    {
        std::cout << "\t " << key << "\t";                         // print key
        for (const auto element : Vec) std::cout << element << " ";// print value
        std::cout << '\n';
    
    }
    

    Remark: As @Jarod42 pointed out in the comments, the given code could be simplified if the entries are known beforehand.

    for example with std::map::emplaceing:

    using ValueType = std::vector<int>;
    std::map<int, ValueType> int_vector;
    int_vector.emplace(1, ValueType{ 2, 5, 7 });
    int_vector.emplace(2, ValueType{ 1, 3, 6 });
    

    or simply initialize the map using the std::initializer_list constructor of the std::map.

    const std::map<int, std::vector<int>> int_vector { {1, {2, 5, 7}}, {2, {1, 3, 6}} };