How do I remove a specific item from my multimap?

56 Views Asked by At
#include <map>
#include <iostream>
 
int main()
{
    std::multimap <int, int> map;
 
    // insert the values in multimap
    map.insert(std::make_pair(1, 10));
    map.insert(std::make_pair(2, 20));
    map.insert(std::make_pair(2, 30));
    map.insert(std::make_pair(2, 40));
    map.insert(std::make_pair(3, 50));
    map.insert(std::make_pair(4, 60));
    map.insert(std::make_pair(4, 70));
     
    int key = 2;   
    bool fo = false;
    for (auto itr = map.begin(); itr != map.end(); itr++)   
    {
      if (itr -> first == key)       
      {  
        if(fo)
        {
          map.erase(itr);
        }
        fo = true;
      }
    }

     for (auto itr = map.begin(); itr != map.end(); itr++)   
     {
                std::cout << itr -> first << "  "
                 << itr -> second << std::endl;
     }

    return 0;
}

The map.erase(itr); is making the last for loop output nothing. The idea is that the last for loop will output my map without the 2s, with the exception of the first 2 because of my bool fo. How can I fix this as to get the desired output I described above?

2

There are 2 best solutions below

0
Sam Varshavchik On BEST ANSWER
map.erase(itr);

The itr iterator is now invalid. When you erase() something from the container, the iterator for the erased value is always invalidated, and depending on the container other iterators may or may not be invalidated. But the issue here is this particular itr. It is now a flaming wreckage.

...; itr++)

... aaaand immediately afterwards this increments invalid iterator. Hillarity ensues.

If you check erase() documentation you will discover that erase() returns the iterator to the next value in the container, what itr++ would've returned. Therefore, the correct approach for something like this

if ( ... your condition goes here ... )
{
    itr=map.erase(itr);
}
else
{
    itr++;
}

And the increment of the iterator is removed from the for loop itself, and done here, as an alernative to erase().

0
Igor Tandetnik On

You don't need to loop over the whole map to find elements with the given key. Quickly looking up elements by key is the whole point of maps. You likely want something like this:

auto [beg, end] = map.equal_range(key);
if (beg != end) {
  map.erase(++beg, end);
}

This erases all but the first element with a given key.