22

Please consider the following situation:

using namespace std;
unordered_map<int, vector<A>> elements;

Now I'm iterating over this unordered map:

for (auto it = elements.begin(); it != elements.end(); ++it)

Inside the loop, I'm forming clusters out of several elements of elements (the current one that it points to and some more, not necessarily those next in line!). Because each element can be only part of one cluster, I'd like to remove those from the map and then continue with the next element (i.e., build the next cluster).

How can I do this and still continue the iteration at the correct position?

Niko
  • 26,516
  • 9
  • 93
  • 110

3 Answers3

43
for (auto it = elements.begin(); it != elements.end();) {
   if(you have to rease) {
      it = elements.erase(it);
   }
   else
      it++;
}

This way you make sure you don't increment after erasing and alos you don't increment the end().

After suggestions that there's no good reason to have for loop that doesn't increment anything you might want to us a while loop instead. Mainly for more readability.

Community
  • 1
  • 1
  • 2
    Style nitpick: there's [no good reason](http://stackoverflow.com/q/1379246/46821) to have a for-loop that doesn't increment anything. This would probably be better as a while-loop. – Michael Kristofik Mar 27 '13 at 15:22
  • 31
    @MichaelKristofik The for-loop is useful here; It serves the purpose of initializing the iterator and restrict its scope. – csl May 20 '15 at 20:36
20

unordered_map::erase will return the iterator past the deleted element.

You would want code along the lines of:

it = myMap.erase( it );

Important note: If you are doing this within a loop, you'll want to make sure that you avoid the typical increment of it at the end of the loop if this is done.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
7

The erase function returns the iterator after the removed element (all collections erase functions do). You can use that to continue.

Just remember to not increase the iterator in the case when you erase an element, or you will step over one element.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • `set::erase()` returns the number of elements removed. – trojanfoe Mar 27 '13 at 15:26
  • Or should I say "the value based version of `erase()` returns the number of elements removed". It's a bit misleading to say "all collections `erase` functions does". – trojanfoe Mar 27 '13 at 15:33