David Sttivend Angel
David Sttivend Angel

Reputation: 123

iterate over multimap <string, map <string,int> >

i want to iterate over all items in a multimap <string,map<string,int>> but just once for each Key, but i cant make it work, here is the code im using to iterate:

for(multimap <string, map <string, int> >::iterator it = myMultimap.begin(); it != myMultimap.end(); it =myMultimap.upper_bound(it->first)){

    //i read that myMultimap.upper_bound(it->first) get the elements of the same key

    pair< multimap <string,map <string, int> >::iterator , multimap <string,map <string, int> >::iterator > ret;
    ret = myMultimap.equal_range(it->first);

    for(multimap <string, map <string, int> >::iterator it2 = ret.first; it2 != ret.second; it2++){


    //here i just want to print map <string , int>
    cout << (*it2).second.first << endl;
    cout << (*it2).second.second << endl;

    }
}

when i run it i get class std::map<std::basic_string<char>, int>’ don't have a member called ‘first’ and same thing for second.second. Sorry about my english is not my mother language.

Upvotes: 1

Views: 1956

Answers (2)

David Sttivend Angel
David Sttivend Angel

Reputation: 123

   map<string, int>::iterator in;

 for(multimap <string, map <string, int> >::iterator it = myMultimap.begin(); it != myMultimap.end(); it =myMultimap.upper_bound(it->first)){



        pair< multimap <string,map <string, int> >::iterator , multimap <string,map <string, int> >::iterator > ret;
        ret = myMultimap.equal_range(it->first);

        for(multimap <string, map <string, int> >::iterator it2 = ret.first; it2 != ret.second; it2++){

            //get the map with begin() and assign it to an iterator
            in = it2->second.begin();
            cout << in->first << " "<< in->second << endl;


        }
    }

Upvotes: 0

kfsone
kfsone

Reputation: 24269

Lets make things easier for ourselves to start with

typedef std::map<std::string, int> InnerMap;
typedef std::multimap<std::string, InnerMap> StringMap;

StringMap myMultimap;

Now, that outer loop

for (StringMap::iterator it = myMultimap.begin(); it != myMultimap.end(); ++it)
{
    std::cout << "[" << it->first << "]:";
    for (InnerMap::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2)
    {
        std::cout << " " << it2->first << ":" << it2->second;
    }
    std::cout << '\n';
}

We can also, if you have C++11, make things simpler by using auto

for (auto it = myMultimap.begin(); it != myMultimap.end(); ++it)
{
    std::cout << "[" << it->first << "]:";
    for (auto it2 = it->second.begin(); it2 != it->second.end(); ++it2)
    {
        std::cout << " " << it2->first << ":" << it2->second;
    }
    std::cout << '\n';
}

What we're doing:

for (StringMap::iterator it = myMultimap.begin(); it != myMultimap.end(); ++it)

This iterates across all of the std::pair<std::string /*key*/, InnerMap /*value*/> elements that actually make up the outer multimap. If you have one key twice, you'll see both entries.

it->first is the std::string key for the current multimap entry, it->second is the InnerMap value of the current entry.

    for (InnerMap::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2)

This iterates over the std::pair<std::string, int> InnerMap elements of the map that is the value of this multimap slot.

--- EDIT ---

Ultimately, using C++11 you could use range based for (not sure why I thought this would be messier)

// use 'auto&' so we take a reference instead of a copy.
for (auto& it : myMultimap)
{
    std::cout << "[" << it.first << "]:";
    for (auto it2 : it.second)
    {
        std::cout << " " << it2.first << ":" << it2.second;
    }
    std::cout << '\n';
}

Note that, in this case, we now use "." instead of "->". This is because we're actually seeing every element (std::pair<...>) in the multimap/map, rather than a simple iterator. That is, it is of type std::pair<std::string, InnerMap>& and it2 is of type std::pair<std::string, int>&.

Upvotes: 1

Related Questions