我目前正在编写一个程序,它在程序中的某一点使用列表,我想迭代三个列表a,b和c,如果b和c中的任何元素出现在a中,则将其删除。我这样做:
//remove elements from OpenList that are in ClosedList
for(list<Node> :: iterator cloIt = ClosedList.begin(); cloIt != ClosedList.end(); cloIt++)
{
for(list<Node> :: iterator opIt = OpenList.begin(); opIt != OpenList.end(); opIt++)
{
for(list<Node> :: iterator neigIt = Neighbour.begin(); neigIt != Neighbour.end(); neigIt++)
{
if (*cloIt == *opIt)
{
opIt = OpenList.erase(opIt);
}
if (*cloIt == *neigIt)
{
neigIt = Neighbour.erase(neigIt);
}
}
}
}然而,这会导致我得到一个“列表迭代器不可递增”的错误,我该如何解决这个问题呢?
发布于 2013-05-01 19:25:17
从你的删除呼叫中,你想要
remove Neighbour items if from listremove Neighbour items如果在ClosedListlist中找到相邻项,则删除相邻项
你最好将代码分成两个循环,而不是嵌套循环,例如:
1.如果在ClosedList list中找到OpenList项,则将其删除
for(auto cloIt = ClosedList.begin(); cloIt != ClosedList.end(); ++cloIt)
{
OpenList.remove_if([&](const Node& n){ return n == *colIt; } );
}2.如果从ClosedListlist中找到相邻项目,则将其移除
for(auto cloIt = ClosedList.begin(); cloIt != ClosedList.end(); ++cloIt)
{
Neighbour.remove_if([&](const Node& n){ return n == *colIt; } );
}很明显,前面的代码是重复的,你可以为此编写一个通用函数:
void RemoveItem(std::list<Node>& node_list, std::list<Node>& node_list2)
{
for(auto cloIt = node_list2.begin(); cloIt != node_list2.end(); ++cloIt)
{
node_list.remove_if([&](const Node& n){ return n == *colIt; } );
}
}现在你可以调用:
RemoveItem(OpenList, CloseList);
RemoveItem(Neighbour, CloseList);更新:不要忘记为节点类型定义operator==,例如,如果节点有getId接口:
bool operator==(const Node& lhs, const Node& rhs)
{
return lhs.getId() == rhs.getId();
}发布于 2013-05-01 19:05:54
我该怎么解决这个问题呢?
最好的方法是使用标准算法,并让它们为您执行迭代、搜索和/或条件删除。
您可以将std::list的remove_if()成员函数与检查元素是否包含在列表a中的lambda谓词一起使用
#include <algorithm>
// ...
b.remove_if(
[&a] (Node const& n)
{
return (std::find(begin(a), end(a), n) != a.end());
});如果元素包含在a中,则与从c中删除元素相同。
另一种可能性是使用std::for_each()遍历a的所有元素,并从b和c中删除它们
#include <algorithm>
// ...
std::for_each(begin(a), end(a),
[&b, &c] (Node const& n)
{
b.remove(n);
c.remove(n);
});发布于 2013-05-01 19:30:35
您已经正确地使用了.erase的返回值来获得新的迭代器,但是忘记了此迭代器在循环的当前迭代结束时立即获得++'d;如果.erase的结果为.end,则这是一个无效操作。
(实际上非常幸运的是,您在尝试递增现在无效的迭代器时得到了诊断结果-标准对这种情况没有任何保证。)
当你没有++ .erase**.**时,你只需要++就可以了
一般的模式如下所示:
for (typename list<T>::iterator it = l.begin(), end = l.end(); it != end; )
{
// ^^ NB. no "it++" in the loop introduction!
if (foo(*it)) {
// condition satisfied; do the erase, and get the next
// iterator from `.erase` and NOT through incrementing
it = l.erase(it);
}
else {
// no erasure; do the increment only in this case
it++;
}
}正如Andy建议的那样,您可以通过使用标准算法来完全避免这个问题。
https://stackoverflow.com/questions/16316899
复制相似问题