2011-03-21 105 views
1

我要循环通过一个向量和擦除对应于一个特定标准的某些元素,例如:通过它循环擦除向量的最后一个元件

vector<int> myvector; 
vector<int>::iterator it; 

myvector.push_back(1); 
myvector.push_back(2); 
myvector.push_back(3); 
myvector.push_back(4); 

for(it = myvector.begin(); it != myvector.end(); ++it){ 

    if((*it) == 4){ 
     it = myvector.erase(it); 
    } 
} 

现在能正常工作,除非该标准擦除最后一个项目就像上面的代码一样。你如何避免这种行为?

谢谢。

编辑------------------------------------

现在我之所以通过它循环是,实际上有4个向量我需要删除元素(但标准只在一个向量):

在这种情况下,这是怎么回事?

vector<int> myvector; 
vector<int> myvector2; 
vector<int> myvector3; 
vector<int> myvector4; 
vector<int>::iterator it; 
vector<int>::iterator it2; 
vector<int>::iterator it3; 
vector<int>::iterator it4; 

myvector.push_back(1); 
myvector.push_back(2); 
myvector.push_back(3); 
myvector.push_back(4); 

(假定myvector2/3/4具有在其内部的值)

it2 = myvector2.begin() 
it3 = myvector3.begin() 
it4 = myvector4.begin() 

for(it = myvector.begin(); it != myvector.end();){ 

    if((*it) == 4){ 
     it = myvector.erase(it); 
     it2 = myvector2.erase(it2); 
     it3 = myvector3.erase(it3); 
     it4 = myvector4.erase(it4); 
    } 
    else{ 
    ++it; 
    ++it2; 
    ++it3; 
    ++it4; 
    } 
} 

是否有一个修改到擦除/删除成语在这种情况下有效?

+0

“现在这个工作正常,除非标准擦除最后一项。” 不,它不。每次删除 元素时,它都有未定义的行为。 (只是以为我会提到这一点;其他人发布了 正确的解决方案。) – 2011-03-21 18:09:29

回答

3

不要用for循环做这件事,你已经有一个调试良好的算法。

myvector.erase(std::remove(myvector.begin(), myvector.end(), 4), myvector.end());

2

我想你应该写循环为:在if块本身

for(it = myvector.begin(); it != myvector.end();) 
{ 
    if((*it) == 4) 
     it = myvector.erase(it); 
    else 
     ++it; //increment here! 
} 

因为在你的代码,如果你发现4,更新it,但在这之后,你又在增加/更新itfor这也是错误的。这就是为什么我把它移到else块,以确保如果你没有找到4it被递增(或任何价值,你正在寻找)。

还记得erase返回iterator pointing to the new location of the element that followed the last element erased by the function call

+1

@Simon:请注意,for循环已更改。这是因为'erase'会返回下一个项目,而'++ it'不是你在这种情况下循环的时候想要做的。 – 2011-03-21 16:55:13

+0

@ John&Nawaz:谢谢,现在我明白了它实际上是++ ++两次,超出最后一个元素 – Simon 2011-03-21 17:05:14

+0

@Simon:两次。究竟! – Nawaz 2011-03-21 17:07:09

5

通常是删除/擦除成语,这将是这个样子:

myvector.erase(std::remove(myvector.begin(), myvector.end(), 4), myvector.end()); 

编辑:重读你的问题,你提到的“一定条件”。如果标准不一定只删除一个值,你可以用std::remove_if代替std::remove,并在函子指定的标准。

EDIT2:为版本处理四个向量,在通常方法是创建一个struct拿着四个相关值,并删除整个结构:

struct x4 { 
    int a, b, c, d; 

    // define equality based on the key field: 
    bool operator==(x4 const &other) { return a == other.a; } 

    x4(int a_, int b_=0, int c_=0, ind d_=0) : a(a_), b(b_), c(c_), d(d_) {} 
}; 

std::vector<x4> myvector; 

myvector.erase(std::remove(myvector.begin(), myvector.end(), x4(4)); 

同样,如果你的条件比较复杂比你可以轻松地表达在比较操作,您可以使用std::remove_if而不是std::remove。如果/您可能需要在不同的时间应用不同的标准,这也很有用。

如果你真的需要保持平行向量(例如,你喂的数据外在的东西,需要单独的,连续的阵列)的数据,然后使用循环可能是因为替代物一样好。

+0

不要忘记,如果有重复项需要从返回迭代器中清除到'end'。 – 2011-03-21 16:56:43

+0

@Mark B:是的 - 已经更正了。不过谢谢。 – 2011-03-21 16:57:53

0

erase通常与remove使用(也有看erase-remove成语),如下图所示

myvector.erase(std::remove(myvector.begin(), myvector.end(), 4), myvector.end()); 
+0

Prasoon:你用'remove'把'erase'弄糊涂了。这是'删除'它实际上不删除元素! – Nawaz 2011-03-21 16:59:55

+0

@Nawaz:已更正 – 2011-03-21 17:00:54

0
for(it = myvector.begin(); it < myvector.end(); ++it){ 

    if((*it) == 4){ 
     it = myvector.erase(it); 
    } 
} 

这将确保你的循环将打破,如果it >= myvector.end()

+0

如果使用这种循环有任何问题,请帮助我更好地理解这个概念。 – 2015-12-28 07:05:47

相关问题