Search code examples
c++dictionarynestedmultimap

Printing multimap within multimap (nested maps)


I am trying to print out a nested multimap but haven't found a way (or a discussion here) to help me solve the problem.

They way I normally print a multimap looks something like this:

template<typename a, typename b>
void printMMap1(std::multimap<a, b>thing){
 for (std::multimap<a,b>::iterator it = thing.begin(); it != thing.end(); it++){
    std::cout << it->first << " : " << it->second << std::endl;
  }
}

But now I want to use the same motivation to print a:

multimap<multimap<a,b>, multimap<c,d>> MAPname;

This doesn't seem to work:

template<typename aa, typename bb, typename cc>
void printMMap(std::multimap<std::multimap<aa, bb>, std::multimap<aa, cc>>thing){
    for (std::multimap<std::multimap<aa, bb>, std::multimap<aa, cc>>::iterator it = thing.begin(); it != thing.end(); it++){
    std::cout << it->first.first << " : " << it->first.second << std::endl <<
            it->second.first << " : " << it->second.second << std::endl;
}

}

Any help/suggestions would be much appreciated!

Thank you for your help.

_EDIT:

Using motivation from hansmaad's example, I came up with something close to the solution I would like (below):

//N.B: I removed the "auto"s for educational purposes (mostly for myself and other beginners)

template<typename a, typename b>
void print1(const std::multimap<a, b>& thing){
for (std::multimap<a,b>::const_iterator it = begin(thing); it != thing.end(); it++){
   std::cout << it->first << " : " << it->second << std::endl;
   }
}



template<typename aa, typename bb, typename cc>
void print2(const std::multimap<std::multimap<aa, bb>, std::multimap<aa, cc>>& thing){
std::multimap<std::multimap<aa, bb>, std::multimap<aa, cc>>::const_reverse_iterator it = thing.rbegin();

//why reverse iterator? Because I noticed that the loop which duplicates the output has a final iteration equal to the desired output, so I only use the last iteration i.e. going backwards ("rbegin")

std::multimap<aa, bb> keyMap = it->first;
std::multimap<aa, cc> valueMap = it->second;

std::cout << "key\n";
print1(keyMap);
std::cout << "value\n";
print1(valueMap);

}

This prints this solution, which is 90% close to what I want. For e.g. it prints:

key
a_key1 : a_value1
a_key2 : a_value1
a_key2 : a_value2
a_key2 : a_value3
a_key3 : a_value1
a_key3 : a_value2
a_key3 : a_value3
a_key3 : a_value4

value
b_key1 : b_value1
b_key1 : b_value2
b_key1 : b_value3
b_key1 : b_value4
b_key2 : b_value1
b_key3 : b_value1
b_key4 : b_value1
b_key4 : b_value2

Whereas I want to print the same output, albeit formatted like so:

key                  value 
a_key1 : a_value1    b_key1 : b_value1
a_key2 : a_value1    b_key1 : b_value2
a_key2 : a_value2    b_key1 : b_value3
a_key2 : a_value3    b_key1 : b_value4
a_key3 : a_value1    b_key2 : b_value1
a_key3 : a_value2    b_key3 : b_value1
a_key3 : a_value3    b_key4 : b_value1
a_key3 : a_value4    b_key4 : b_value2

A slight difference. I smell I am close.


Solution

  • I am not sure what you expect as output from your printMMap function, but the problem with your code is it->first.first

    template<typename aa, typename bb, typename cc>
    void printMMap(std::multimap<std::multimap<aa, bb>, std::multimap<aa, cc>>thing){
        for (std::multimap<std::multimap<aa, bb>, std::multimap<aa, cc>>::iterator it = thing.begin(); it != thing.end(); it++){
                // std::multimap<aa, bb> x = it->first;
                // std::multimap<aa, bb> y = it->second;
                // x, y don't have a member 'first', they are multimaps
                // broken:
                std::cout << it->first.first /*...*/ it->second.second << std::endl;
        }
    }
    

    You could do for example:

    template<typename a, typename b>
    void print(const std::multimap<a, b>& thing){
        for (auto it = begin(thing); it != end(thing); ++it){
            std::cout << it->first << " : " << it->second << std::endl;
        }
    }
    
    template<typename aa, typename bb, typename cc>
    void print(const std::multimap<std::multimap<aa, bb>, std::multimap<aa, cc>>& thing){
        for (auto it = begin(thing); it != end(thing); ++it){
            auto& keyMap = it->first;
            auto& valueMap = it->second;
            std::cout << "key\n";
            print(keyMap);
            std::cout << "value\n";
            print(valueMap);
        }
    }
    

    Which will print for

        multimap<multimap<int, int>, multimap<int, int>> mmap;
        multimap<int, int> key{ { 1, 1 }, { 1, 2 }, { 2, 4 } };
        multimap<int, int> value{ { 10, 1 } };
        mmap.emplace(move(key), move(value));
        print(mmap);
    
    
    >key
    >1 : 1
    >1 : 2
    >2 : 4
    >value
    >10 : 1