Стирание элементов в векторе

Так у меня есть вектор беззнаковых целых (vector<unsigned int> называется vector1). У меня есть другой вектор структуры, которую я создал (vector<struct> называется vector2). vector<int> содержит целое число, которое является индексом vector<struct>, Например, скажем, что vector<int = {5, 17, 18, 19}, Это означает vector2.at(5) == vector2.at(vector1.at(0)),

В структуре у меня есть переменная bool под названием var, В большинстве случаев, var ложно Я хочу удалить все элементы в vector1 который имеет var = правда.

То, что я сделал, было:

for (unsigned int i = 0; i < vector1.size(); i++)
{
if (vector2.at(vector1.at(i)).var)
vector1.erase(vector.begin() + i);
}

Единственная проблема в том, что он не удаляет все истинные элементы. Я запустил цикл for несколько раз для удаления всех значений. Это правильное поведение? Если нет, то где я ошибся?

0

Решение

Вы должны использовать стереть-удалить идиому удалить элементы из вектора.

v.erase(std::remove(v.begin(), v.end(), value), v.begin);

std::remove перемещает элементы в конец вектора и erase удалит элемент из вектора.

3

Другие решения

Вы можете сохранить временный вектор, копию vector1 и перебрать его в for цикл и удалить из vector1,

1

Вы стираете элементы в векторе, одновременно перебирая его. Поэтому при стирании элемента вы всегда перепрыгиваете через следующий элемент, так как увеличиваете i просто укоротив вектор в i (было бы еще хуже, если бы вы использовали правильный цикл итератора вместо цикла индекса). Лучший способ сделать это — разделить обе функции, сначала «Маркировка» (или, вернее, переупорядочение) элементов для удаления и последующего удаления их из вектора.

На практике это лучше всего сделать, используя стереть-удалить идиому (vector.erarse(std::remove(...), vector.end())), который первым использует std::remove(_if) реорганизовать данные с не удаленными элементами в начале и вернуть новый конец диапазона, который затем можно использовать для реального удаления этих удаленных элементов из диапазона (эффективно просто сокращая весь вектор), используя std::vector::erase. Используя лямбду C ++ 11, условие удаления может быть выражено довольно легко:

vector1.erase(std::remove_if(                        //erase range starting here
vector1.begin(), vector1.end(),    //iterate over whole vector
[&vector2](unsigned int i)         //call this for each element
{ return vector2.at(i).var; }),  //return true to remove
vector1.end());                        //erase up to old end

РЕДАКТИРОВАТЬ: И, кстати, как всегда будьте уверены, если вам действительно нужно std::vector::at вместо просто [] и имейте в виду последствия обоих (в частности, накладные расходы первого и «может быть незащищенность» из последних).

1
По вопросам рекламы [email protected]