Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to iterate over a STL set and selectively remove elements?

Tags:

c++

set

stl

The following code does not work correctly. How should it be done correctly?

for (std::set<Color>::iterator i = myColorContainer.begin();
            i!=myColorContainer.end();
            ++i)
{
    if ( *i  == Yellow)
    {
        DoSomeProccessing( *i );
        myColorContainer.erase(i);
    }
}
like image 918
zr. Avatar asked Jun 16 '10 10:06

zr.


3 Answers

Try:

for(std::set<Color>::iterator it = myColorContainer.begin(); 
    it != myColorContainer.end();) { // note missing it++
     if( (*it) == Yellow ) {
        DoSomeProcessing(*it);
        myColorContainer.erase(it++); // post increment (original sent to erase)
     }
     else {
       ++it; // more efficient than it++;
     }
}
like image 74
Adrian Regan Avatar answered Nov 12 '22 19:11

Adrian Regan


You don't need a loop as youre dealing with a set.

std::set<Color>::iterator it = myColorContainer.find(Yellow);
if (it != it.myColorContainer.end()){
  DoSomeProcessing(*it);
  myColorContainer.erase(it);
}
like image 6
Viktor Sehr Avatar answered Nov 12 '22 21:11

Viktor Sehr


for (std::set<Color>::iterator i = myColorContainer.begin();
            i!=myColorContainer.end(); /* No i++ */)
{
    if ( *i  == Yellow)
    {
        DoSomeProccessing( *i );
        std::set<Color>::iterator tmp = i;
        ++i;
        myColorContainer.erase(tmp);
    }
    else {
        ++i;
    }
}

Once you go to next message with ++i it is guaranteed to be valid - property of std::set that iterators on inserted elements are never invalidated unless the element is removed.

So now you can safely erase previous entry.

like image 2
Artyom Avatar answered Nov 12 '22 20:11

Artyom