Стирание последнего элемента вектора путем его циклического перемещения - PullRequest
1 голос
/ 21 марта 2011

Я хочу перебрать вектор и стереть определенные элементы, которые соответствуют определенным критериям, например:

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 ]

5 голосов
/ 21 марта 2011

Обычно используется идиома удаления / удаления, которая выглядит примерно так:

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.Это также полезно, если / когда вам может понадобиться применять разные критерии в разное время.

Если вам действительно нужно , чтобы хранить ваши данные в параллельных векторах (например, вы подаете данныек чему-то внешнему, что требует отдельных смежных массивов), тогда использование цикла, вероятно, так же хорошо, как альтернативы.

3 голосов
/ 21 марта 2011

Не делайте этого с циклом for, для вас уже есть отлаженный алгоритм.

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

2 голосов
/ 21 марта 2011

Я думаю, вы должны написать цикл как:

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

Потому что в вашем коде, если вы найдете 4, вы обновите it в самом блоке if, но после этого вы снова увеличите / обновите it в for, что также неверно. Вот почему я переместил его в блок else, который гарантирует увеличение it, если вы не найдете 4 (или любое другое значение, которое вы ищете).

Также помните, что erase возвращает итератор , указывающий на новое местоположение элемента, который следует за последним элементом, удаленным при вызове функции .

0 голосов
/ 28 декабря 2015
for(it = myvector.begin(); it < myvector.end(); ++it){

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

Это обеспечит разрыв вашего цикла, если it >= myvector.end().

0 голосов
/ 21 марта 2011

erase обычно используется с remove (также посмотрите на erase-remove идиома), как показано ниже

myvector.erase(std::remove(myvector.begin(), myvector.end(), 4), myvector.end());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...