C++在迭代列表时删除列表中的元素

4

我有一个std::listBananas,我想把坏的都除掉。是否有相对简单的方法来执行以下伪代码?

foreach(Banana banana in bananaList)
{
    if(banana.isBad()) bananaList.remove(banana);
}

从C#和Java转向C++一直是一条崎岖的道路。

1
https://dev59.com/qXNA5IYBdhLWcg3wPbSe - YuppieNetworking
@YuppieNetworking:相应的问题通常可以得到解决,但它并不是最好的解决方案,因为该提问者想要在成员函数返回 true 的情况下删除一个元素。 - Billy ONeal
3个回答

7
bananaList.remove_if(std::mem_fun_ref(&Banana::isBad));

请注意,您应该使用std::vector而不是std::list,因为在99.9%的情况下,vector的性能更好,并且更容易使用。
编辑:如果您正在使用向量,则向量没有remove_if成员函数,因此您必须使用名称空间std中的普通remove_if
bananaVector.erase(
    std::remove_if(bananaVector.begin(), bananaVector.end(), std::mem_fun_ref(&Banana::isBad)), 
    bananaVector.end());

真的吗?我认为如果我要从列表中删除很多东西,那么std :: list是最好的选择。 - JnBrymn
@John:std::list 使得删除本身很快(O(1)),但是找到正确的位置相对较慢(O(N),通常比向量更高的常数)。 - Jerry Coffin
2
@John:由于更好的缓存局部性,在实践中,std::vector通常比理论上的std::list表现更好。你需要进行测量。 - sbi
1
@Martin York:对于std::remove_if,您是正确的。但是对于std::list<t>::remove_if,成员函数会为您处理这个问题。 - Billy ONeal
@Billy ONeal:这就是为什么我说“并不是说有人这样做了”。而且我认为std::wstring构造函数并不算太昂贵。我指的是更复杂的对象。 - Torlack
显示剩余3条评论

1

通常情况下,您会做这样的事情:

list.erase(std::remove_if(list.begin(), list.end(), std::mem_fun(Banana::isBad)), list.end());

编辑:由于remove_if被实现为std::list的成员函数,Billy ONeal的答案可能是更好的方法来完成所描述的工作,尽管当/如果您决定使用向量、双端队列等时,这将更容易转换,正如已经在评论中讨论的那样,这可能是一个好主意。

0

你可以使用自制代码,例如

for(list<...>::iterator it=bananas.begin(); end=bananas.end(); it!=end;) {
  if(... decide ...) {
    it=bananas.erase(it);
  } else
    ++it;
}

或者,你可以使用 list::remove_if 方法,或者 std::remove_if 函数(在 vector 中也可用)。


在编程中,我们应该始终优先选择算法而不是显式循环。 - Billy ONeal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接