迭代通过STL容器和删除/添加多个项目 [英] Iterating through STL containers and removing/adding multiple items
问题描述
在我的代码中发生的最常见的错误之一是,STL容器在循环期间被修改。
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.
for循环通常看起来像这样:
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.
这里是一些伪代码来说明发生这种情况时: / p>
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
我们从 0
开始循环并逐个元素。在 4
,我要删除 1
, 4
和 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.
推荐答案
使用 std :: remove_if
和决定是否需要删除按钮的谓词:
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 :对于最后一个例子, )算法是:
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).
这篇关于迭代通过STL容器和删除/添加多个项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!