std::vector.erase() 只擦除它应该擦除的一半

Posted

技术标签:

【中文标题】std::vector.erase() 只擦除它应该擦除的一半【英文标题】:std::vector.erase() only erases half of what it should 【发布时间】:2021-06-26 15:03:09 【问题描述】:

我有一个程序,我必须在其中删除结构向量的一些条目。我是这样做的

  for(int i=0; i<molec.size(); i++)
    
      if(!molec[i].mine)
        molec.erase(molec.begin()+i);
    

molec.mine 是结构中定义的布尔值。问题是,当我这样做时,它会删除一半的具有 molc.mine=false 的元素。我试图寻找一些替代方案,发现我可以做到这一点

vector.erase(std::remove(vec.begin(),vec.end(),1963),vec.end());

问题在于我不知道如何使用结构向量来实现。

我该如何解决这个问题?

【问题讨论】:

第一个示例中的代码从不查看紧跟在已擦除元素之后的元素;换句话说,它永远不会删除两个相邻的元素。 所以你知道当你删除一个元素时,它会移动其他元素吗?如果a[i] 将被删除,则意味着a[i+1] 将变为 a[i]a[i+2] 将变为a[i+1]。那么无条件递增i 会做什么呢?我认为您可能会从阅读"How to debug small programs" 中受益。 哦,我明白了。我现在知道了。谢谢 【参考方案1】:

您可能正在寻找std::remove_if。如

molec.erase(
  std::remove_if(
    molec.begin(), molec.end(),
    [](const auto& elem)  return !elem.mine; ),
  molec.end());

【讨论】:

是的,这正是我所需要的。谢谢。【参考方案2】:

当元素为erased 时,不应执行i++。例如

for(int i=0; i<molec.size(); )

  if(!molec[i].mine)
    molec.erase(molec.begin()+i);
  else
    i++;

是的,您应该使用算法库来避免此类问题。

molec.erase(std::remove_if(molec.begin(),molec.end(),[](const auto& v)  return !v.mine;),molec.end());

【讨论】:

谢谢,这正是我所需要的

以上是关于std::vector.erase() 只擦除它应该擦除的一半的主要内容,如果未能解决你的问题,请参考以下文章

在 std::multiset 中,如果找到一个元素,是不是有一种函数或算法可以只擦除一个样本(单一或重复)

为啥对话框会在不刷新的情况下删除其内容?

为什么对话框会在不刷新的情况下删除其内容

Fabric.js 橡皮擦问题画布

iframe 中的彗星服务器数据是不是只是累积?

为啥我不能删除字符串的数字字符?