как удалить элементы из контейнера vector в цикле
От: serega3000  
Дата: 28.10.06 20:24
Оценка:
Искал повсюду и не нашел.
Насколько я знаю, после удаления элемента из контейнера итератор теряет свою значимость.
Значит, так делать нельзя:

vector<int> v;
vector<int>::iterator it;
for(it=v.begin();it!=v.end();it++)if(условие)v.erase(it);


А как же тогда поступить, что-бы можно было перебрать все эл-ты, и одновременно некоторые из них удаляя???
Re: как удалить элементы из контейнера vector в цикле
От: vayerx  
Дата: 28.10.06 21:23
Оценка:
Здравствуйте, serega3000, Вы писали:

S>Насколько я знаю, после удаления элемента из контейнера итератор теряет свою значимость.


Не совсем так. vector::erase() делает недействительными все итераторы после удаляемой позиции. Соответственно, если идти от конца массива к его началу декрементируя итератор, проблем с удалением не будет.
Re[2]: как удалить элементы из контейнера vector в цикле
От: serega3000  
Дата: 28.10.06 21:36
Оценка:
Здравствуйте, vayerx, Вы писали:

S>>Насколько я знаю, после удаления элемента из контейнера итератор теряет свою значимость.


V>Не совсем так. vector::erase() делает недействительными все итераторы после удаляемой позиции. Соответственно, если идти от конца массива к его началу декрементируя итератор, проблем с удалением не будет.


Спасибо, но оказывается все еще проще. erase возращает итератор на тот элемент, который занимает место удаленного.

for(it=v.begin();it!=v.end();)if(условие)v.erase(it);else it++;
Re[3]: как удалить элементы из контейнера vector в цикле
От: vayerx  
Дата: 28.10.06 23:18
Оценка:
Здравствуйте, serega3000, Вы писали:

S>Спасибо, но оказывается все еще проще. erase возращает итератор на тот элемент, который занимает место удаленного.


S>
S>for(it=v.begin();it!=v.end();)if(условие)v.erase(it);else it++;
S>


Во-первых, в этом случае добавляется дополнительная ветка.
Во-вторых, код не совсем корректен, так как возможен инкремент итератора, находящегося в конце массива.
Re: как удалить элементы из контейнера vector в цикле
От: rm822 Россия  
Дата: 28.10.06 23:56
Оценка:
Здравствуйте, serega3000, Вы писали:

S>Искал повсюду и не нашел.

S>Насколько я знаю, после удаления элемента из контейнера итератор теряет свою значимость.
S>Значит, так делать нельзя:

S>
S>vector<int> v;
S>vector<int>::iterator it;
S>for(it=v.begin();it!=v.end();it++)if(условие)v.erase(it);
S>


S>А как же тогда поступить, что-бы можно было перебрать все эл-ты, и одновременно некоторые из них удаляя???

S>


правильно вот так, обещают что будет работать для любых контейнеров

vector<int> v;
vector<int>::iterator it;
for( it = v.begin(); it != v.end(); )
{
 if (condition)
     it = v.erase(it);
 else
   ++it;
}
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: как удалить элементы из контейнера vector в цикле
От: alexeiz  
Дата: 29.10.06 06:52
Оценка: 1 (1) +1
Здравствуйте, serega3000, Вы писали:

S>Искал повсюду и не нашел.

S>Насколько я знаю, после удаления элемента из контейнера итератор теряет свою значимость.
S>Значит, так делать нельзя:

S>
S>vector<int> v;
S>vector<int>::iterator it;
S>for(it=v.begin();it!=v.end();it++)if(условие)v.erase(it);
S>


S>А как же тогда поступить, что-бы можно было перебрать все эл-ты, и одновременно некоторые из них удаляя???

S>

Твой алгоритм имеет квадратичную сложность. Правильно применять пару erase/remove_if вот таким образом:
struct condition
{
    bool operator()(int) { условие; }
};

v.erase(std::remove_if(v.begin(), v.end(), condition()), v.end());  // линейная сложность


PS: читай Effective STL.
Re: как удалить элементы из контейнера vector в цикле
От: Аноним  
Дата: 29.10.06 09:18
Оценка:
Здравствуйте, serega3000, Вы писали:

S>Искал повсюду и не нашел.

S>Насколько я знаю, после удаления элемента из контейнера итератор теряет свою значимость.
S>Значит, так делать нельзя:

S>
S>vector<int> v;
S>vector<int>::iterator it;
S>for(it=v.begin();it!=v.end();it++)if(условие)v.erase(it);
S>


S>А как же тогда поступить, что-бы можно было перебрать все эл-ты, и одновременно некоторые из них удаляя???

S>

моно использовать алгоритм remove_if и интервальную форму erase так:

bool IsRule(vector<int>& aVar ..... )
{
bool ok = false;
if (условие)
ok = true;

return ok;
}


много кода
.......................

vector<int> v;

заполнение v


много кода
....................


v.erase(remove_if(v.begin(), v.end(), IsRule(v)), v.end());

....................
Re[2]: как удалить элементы из контейнера vector в цикле
От: McQwerty Россия  
Дата: 30.10.06 11:52
Оценка: +1
Здравствуйте, rm822, Вы писали:

R>правильно вот так, обещают что будет работать для любых контейнеров

R>vector<int> v;
R>vector<int>::iterator it;
R>for( it = v.begin(); it != v.end(); )
R>{
R> if (condition)
R>     it = v.erase(it);
R> else
R>   ++it;
R>}

Для карты (std::map) не будет:
namespace std
{
    template <...> class map
    {
    void erase (iterator position);
    };
}
Re[4]: как удалить элементы из контейнера vector в цикле
От: Аноним  
Дата: 31.10.06 08:20
Оценка:
Здравствуйте, vayerx, Вы писали:

S>>
S>>for(it=v.begin();it!=v.end();)if(условие)v.erase(it);else it++;
S>>


V>Во-вторых, код не совсем корректен, так как возможен инкремент итератора, находящегося в конце массива.

Что-то я не усматриваю ситуацию, когда будет проверяться "условие" и итератор будат равен v.end(). Ведь перед этой проверкой идёт проверка на it!=v.end()...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.