Search code examples
c++dictionaryiteratorshared-ptr

Accessing elements in maps of maps with vectors of shared pointers


I have a somewhat unique situation that I can't quite get working.

I've followed a lot of examples of using maps of maps but the vector of shared pointers seems to throw me off a bit.

Suppose I have the following:

typedef boost::shared_ptr<RecCounts> RecCountsPtr;
typedef std::vector<RecCountsPtr> RecCountsPtrVec;
typedef std::map<std::string, RecCountsPtrVec> InnerActivityMap;
typedef std::map< std::string, InnerActivityMap > ActivityMap;

Where RecCounts is a simple structure.

Now, I think I've figured out how to populate my ActivityMap properly.

RecCountsPtr recCountsPtr(new RecCounts());
config.actType = "M";
config.mapDate = "2010/07";

recCountsPtr->iHousehold = "50";
recCountsPtr->iZero = "150";

config.actMap[config.actType][config.mapDate].push_back(recCountsPtr);

Yes? I don't get any compile/runtime errors for this...but since I haven't figured out how to access all the different elements of the map I can't confirm this!

This is the config structure:

struct Config
{
    std::string actType;
    std::string mapDate;

    // Map
    ActivityMap actMap;
    InnerActivityMap innerActMap;

    //Iterator
    ActivityMap::iterator actMapIter;
    InnerActivityMap::iterator innerActMapIter;
};

Now, suppose I want to access each element of the ActivityMap. How would I get the following elements?

The outer map Key?

for (config.actMapIter= config.actMap.begin();
     config.actMapIter != config.actMap.end();
     ++config.actMapIter)
    {
        std::cout << "Outer Key = "
                  << (*config.actMapIter).first << std::endl;
    }

This seemed to do the trick.

The inner map Key? I can't figure this out.

The inner map vector elements?

I can do it like this if I know the two keys:

config.actMap[config.actType][config.mapDate][0]->iHouehold
config.actMap[config.actType][config.mapDate][0]->iZero

...but can't seem to figure out how to iterate through them. :(

This is what I've done to try and iterate through all elements.

for (config.actMapIter= config.actMap.begin();
         config.actMapIter != config.actMap.end();
         ++config.actMapIter)
    {
        std::cout << "Outer Key = " << (*config.actMapIter).first << std::endl;
        for (config.innerActMapIter = config.innerActMap.begin();
             config.innerActMapIter != config.innerActMap.end();
             ++config.innerActMapIter)
        {
            std::cout << "Inner Key = " 
                      << (*config.innerActMapIter).first << std::endl;
            for (size_t i = 0;
                 i < config.actMap[(*config.actMapIter).first]
                                  [(*config.innerActMapIter).first].size();
                 ++i)
            {
                std::cout << "iHousehold = "
                          << config.actMap[(*config.actMapIter).first]
                                          [(*config.innerActMapIter).first]
                                          [i]->iHousehold << std::endl;

                std::cout << "iZero = "
                          << config.actMap[(*config.actMapIter).first]
                                          [(*config.innerActMapIter).first]
                                          [i]->iZero << std::endl;
            }
        }
    }

I don't get any errors but I only get the outer key print to the screen:

Outer Key = M

I suspect something is amiss with my inner iterator...in that it's not associated the ActivityMap. Even if I am correct I don't know how to make such an association.

Any suggestions?

ANSWER (thanks to crashmstr):

Here is a verbose version of the answer suggested by crashmstr.

for (config.actMapIter= config.actMap.begin();
     config.actMapIter != config.actMap.end();
     ++config.actMapIter)
{
    std::cout << "Outer Key = " << (*config.actMapIter).first << std::endl;

    InnerActivityMap innerActMap = (*config.actMapIter).second;
    InnerActivityMap::iterator innerActMapIter;

    for (innerActMapIter = innerActMap.begin();
         innerActMapIter != innerActMap.end();
         ++innerActMapIter)
    {
        std::cout << "Inner Key = " << (*innerActMapIter).first << std::endl;
        for (size_t i = 0;
             i < config.actMap[(*config.actMapIter).first][(*innerActMapIter).first].size();
             ++i)
        {
            std::cout << "iHousehold = "
                      << config.actMap[(*config.actMapIter).first]
                                      [(*innerActMapIter).first]
                                      [i]->iHousehold << std::endl;

            std::cout << "iZero = "
                      << config.actMap[(*config.actMapIter).first]
                                      [(*innerActMapIter).first]
                                      [i]->iZero << std::endl;
        }
    }
}

I get the following printed to the screen:

Outer Key = M

Inner Key = 2010/07

iHousehold = 50

iZero = 150


Solution

  • When iterating over a map, .first is the "key", and .second is the data that belongs to that key.

    So in your case:

    for (config.actMapIter= config.actMap.begin();
        config.actMapIter != config.actMap.end();
        ++config.actMapIter)
    {
        std::cout << "Outer Key = " << (*config.actMapIter).first << std::endl;
        //(*config.actMapIter).second is a std::map<std::string, RecCountsPtrVec>
        //create a new for loop to iterate over .second
    }