Search code examples
c++c++11stlc++14

Convert multimap<Key,Value> to vector<vector<Value>>


I need to convert an std::unordered_multimap<Key,T> to an std::vector<std::vector<T>>. I need to do this because my program will need to sort all the data, and maps can't be sorted. An example:

// Map:
{ "A", 1 },
{ "A", 3 },
{ "A", 2 },
{ "B", 5 }, 
{ "B", 2 },

// Map converted to vector<vector<Value>>:
{ 1, 3, 2 }, 
{ 5, 2 }

Right now I have this code which works. But I'm wondering if it's the best way to do it.

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

int main()
{
    typedef std::string Key_t;
    typedef int Value_t;
    typedef std::unordered_multimap<Key_t, Value_t> Map_t;

    const Map_t map = {
        { "A", 1 }, 
        { "A", 3 }, 
        { "A", 2 },
        { "B", 5 }, 
        { "B", 2 },
    };

    std::vector< std::vector< Value_t > > output;

    for ( Map_t::const_iterator it = map.cbegin(); it != map.cend(); )
    {
        std::vector< Value_t > temp;
        const Map_t::const_iterator end = map.upper_bound( it->first );
        for ( ; it != end; ++it )
            temp.push_back( it->second );

        output.push_back( temp );
    }

    // Print the result
    for ( const std::vector< Value_t >& values : output )
    {
        for ( const Value_t& value : values )
            std::cout << value << " ";

        std::cout << std::endl;
    }
}

Output:

1 3 2
5 2

So, now I'm wondering if there's a faster/better way.


Solution

  • The usual multimap iteration should work here:

    std::vector<std::vector<T>> out;
    
    for (auto it1 = m.begin(), it2 = it1, end = m.end(); it1 != end; it1 = it2)
    {
        out.emplace_back();
        for ( ; it1->first == it2->first; ++it2)
        {
            out.back().push_back(it2->second);
        }
    }