我正在编写一个程序,在所述程序中的某一点使用列表我想迭代3个三个列表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);
}
}
}
}
然而,这导致我得到“List iterator not incrementable”错误 我怎么能解决这个问题?
答案 0 :(得分:1)
从你的擦除电话中,你想要
- 删除OpenList项目(如果在ClosedList列表中找到它们)
- 删除从ClosedListlist
中找到的邻居项目 醇>
您最好将代码分成两个循环,而不是嵌套循环,例如:
1.如果在ClosedList列表中找到它们,则删除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);
<强>更新强> 不要忘记为Node类型定义operator ==,例如,如果node具有getId接口:
bool operator==(const Node& lhs, const Node& rhs)
{
return lhs.getId() == rhs.getId();
}
答案 1 :(得分:0)
我怎么能解决这个问题?
最好的方法是使用标准算法,让他们为您进行迭代,搜索和/或条件删除。
您可以将std::list
的{{3}}成员函数与lambda谓词一起使用,该谓词检查该元素是否包含在列表a
中:
#include <algorithm>
// ...
b.remove_if(
[&a] (Node const& n)
{
return (std::find(begin(a), end(a), n) != a.end());
});
如果c
中包含元素,则删除a
中的元素。
另一种可能性是使用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);
});
答案 2 :(得分:0)
您已正确使用.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建议的那样,你可以通过使用标准算法完全避免这个问题。