Search code examples
c++multimap

Copy subset of multimap into a new multimap


// this has data from elsewhere, just showing its the same type
multimap<string,string> map_with_data;
string string_key = "some_string";

// not working:
multimap<string,string> new_map;

new_map = map_with_data[string_key];

I want a return of a multimap with only the key pairs with the key string_key. What is the right way to do this or is this method of direct copying even possible?

I'm getting: error: no match for ‘operator[]’ (operand types are ‘std::multimap<std::basic_string<char>, std::basic_string<char> >’ and ‘std::string {aka std::basic_string<char>}’)|


Solution

  • Something like the following would be my first choice:

    auto r = map_with_data.equal_range(string_key);
    
    multimap<string, string> new_map(r.first, r.second);
    

    This finds all the items in the existing map with the specified key, then initializes the new map from those iterators. If there is no item in the existing map with that key, you'll get map_with_data.end() for both r.first and r.second, so your new_map will end up empty (as you'd probably expect).

    If you really wanted to, you could use lower_bound and upper_bound instead of equal_range:

    multimap<string, string> new_map {
        map_with_data.lower_bound(string_key), 
        map_with_data.upper_bound(string_key) };
    

    I prefer the code using equal_range though.

    Demo code:

    #include <map>
    #include <string>
    #include <iostream>
    #include <iterator>
    
    using namespace std;
    
    namespace std {
        ostream &operator<<(ostream &os, pair<string, string> const &p) {
            return os << "(" << p.first << ", " << p.second << ")";
        }
    }
    
    int main() {
    
        multimap<string, string> map_with_data {
            {"A", "B"},
            {"A", "C"},
            {"B", "B"},
            {"B", "C"}
        };
    
        auto r = map_with_data.equal_range("A");
    
        multimap<string, string> new_map(r.first, r.second);
    
        copy(new_map.begin(), new_map.end(), 
            ostream_iterator<pair<string, string>>(std::cout, "\n"));
    }
    

    Result:

    (A, B)
    (A, C)