Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterating through STL containers and removing/adding multiple items

Tags:

c++

c++11

One of the most frequent errors that occur in my code is that STL containers are modified during a loop.

Elements are removed or added during a loop execution so I usually run into out of bounds exceptions.

My for loops usually looks like this:

for (auto& Item : Items) { // Will not work when Items container is modified
    //... loop logic
}

When multiple items can be removed, I use this monstrosity:

for (int Index=Items.size()-1;Index<=0;Index--) {
    if (Index<Items.size()) { //Because multiple items can be removed in a single loop
        //... loop logic
    }
}

This looks bad and it makes me feel bad using that second option. The reason multiple items can be removed is due to events, where a single event can remove any number of elements.

Here is some pseudo code to illustrate when this occurs:

// for each button in vector<button> {
// process button events
// event adds more buttons to vector<button>
// *ERROR* vector<button> is modified during loop.
// }

In another example, imagine a vector with following items:

// 0 1 2 3 4 5 6 7 8 9

We start our loop at 0 and go element by element. At 4, I want to remove elements 1,4 and 9 so we can't use a normal loop here.

like image 529
Grapes Avatar asked Dec 14 '25 23:12

Grapes


1 Answers

Use std::remove_if with a predicate that decide if a button needs to be removed:

bool needsRemoved(const Button& button);

vec.erase(std::remove_if(vec.begin(), vec.end(), &needsRemoved), vec.end());

EDIT: For your last example, the quadratic (i.e. bad for performance) algorithm is:

std::vector<int> vec = {0,1,2,3,4,5,6,7,8,9};
auto end = vec.end();
for (auto it = vec.begin(); it < end; ++it)
{
    std::set<int> bad = {1, 4, 9};
    end = std::remove_if
        (vec.begin(), end,
         [bad](int x) { return (bad.find(x) != bad.end()); });
}
vec.erase(end, vec.end());

You will probably be better off using a container with fast lookup though (like a set, or a map).

like image 55
rectummelancolique Avatar answered Dec 16 '25 15:12

rectummelancolique



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!