通过循环遍历向量的最后一个元素

时间:2011-03-21 16:49:39

标签: c++ vector

我想遍历一个向量并删除某些符合某个条件的元素,例如:

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);
    }
}

现在这个工作正常,除非标准删除了上面代码中的最后一项。你怎么避免这种行为?

感谢。

EDIT ------------------------------------

现在我循环的原因是我需要从中删除元素的实际上有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;
    }
}

在这种情况下,擦除/删除习惯用法是否有效?

5 个答案:

答案 0 :(得分:5)

通常是删除/删除习惯用法,它看起来像这样:

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

编辑:重读你的问题,你提到“某些标准”。如果条件不一定仅删除单个值,则可以使用std::remove_if代替std::remove,并在仿函数中指定条件。

Edit2:对于处理四个向量的版本,通常的方法是创建一个包含四个相关值的结构,并删除整个结构:

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。如果/当您可能需要在不同时间应用不同的标准时,这也很有用。

如果你真的需要将数据保存在并行向量中(例如,你将数据提供给需要单独的,连续数组的外部数据),那么使用循环可能就像替代方案。

答案 1 :(得分:3)

不要使用for循环执行此操作,已经有一个经过良好调试的算法。

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

答案 2 :(得分:2)

我认为你应该把循环写成:

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

因为在您的代码中,如果您找到4,则会更新it块本身中的if,但之后您再次在it中增加/更新for {1}}这也是错的。这就是我将其移至else块的原因,如果您没有找到it(或您正在搜索的任何值),则会确保4增加。

另请注意,erase会返回iterator pointing to the new location of the element that followed the last element erased by the function call

答案 3 :(得分:0)

erase通常与remove一起使用(另请查看erase-remove成语),如下所示

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

答案 4 :(得分:0)

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

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

如果it >= myvector.end()

,这将确保您的循环中断