Russian Qt Forum

Программирование => С/C++ => Тема начата: foufou от Сентябрь 13, 2010, 09:00



Название: удаление элементов из вектора
Отправлено: foufou от Сентябрь 13, 2010, 09:00
Есть у меня вектор vector<double>* dat (именно вектор, а не QVector - таково требование заказчика).

Правильно ли я понимаю, что единственный способ удалять из него элементы - это удалять при помощи метода erase по-одному ? Т.е. нельзя удалить сразу пачкой ?
Кроме того, на удаляемый элемент нужно установить итератор, типа вот так:

vector<double>::iterator it = dat->begin();
for (int i = 0; i < index; i++)
{
      it++;
}

А потом могу удалять выбранный элемент из вектора:

dat->erase(it);

Чтобы удалить N элементов, следующих подряд, повторить последнюю строку N раз.

Можно ли как-то проще удалить из середины вектора пачку элементов в N штук ?


Название: Re: удаление элементов из вектора
Отправлено: Пантер от Сентябрь 13, 2010, 09:05
iterator erase ( iterator first, iterator last );
Т.е. тебе нужно указать интервал для удаления.


Название: Re: удаление элементов из вектора
Отправлено: foufou от Сентябрь 13, 2010, 09:42
Спасибо !
А есть ли возможность установить итератор на первый удаляемый элемент "сразу" ? Т.е. без цикла типа

for (int i = 0; i < index; i++)
{
      it++;
}

?


Название: Re: удаление элементов из вектора
Отправлено: BRE от Сентябрь 13, 2010, 09:54
Почитай что что нибудь по C++ и STL.
Стандартный пример:
Код
C++ (Qt)
// erasing from vector
#include <iostream>
#include <vector>
using namespace std;
 
int main ()
{
 unsigned int i;
 vector<unsigned int> myvector;
 
 // set some values (from 1 to 10)
 for (i=1; i<=10; i++) myvector.push_back(i);
 
 // erase the 6th element
 myvector.erase (myvector.begin()+5);
 
 // erase the first 3 elements:
 myvector.erase (myvector.begin(),myvector.begin()+3);
 
 cout << "myvector contains:";
 for (i=0; i<myvector.size(); i++)
   cout << " " << myvector[i];
 cout << endl;
 
 return 0;
}
 


Название: Re: удаление элементов из вектора
Отправлено: foufou от Сентябрь 13, 2010, 21:46
Спасибо ! Заработало ! :)


Название: Re: удаление элементов из вектора
Отправлено: Igors от Сентябрь 14, 2010, 16:36
Правильно ли я понимаю, что единственный способ удалять из него элементы - это удалять при помощи метода erase по-одному ? Т.е. нельзя удалить сразу пачкой ?
Все сказанное выше об erase правильно, но при всем этом erase для вектора - удовольствие дорогое. Поэтому если есть возможность лучше обойтись без него

Код
C++ (Qt)
// удаляем все отрицательные элементы
void DeleteNegatives( std::vector<double> & vec )
{
 size_t i, place = 0, limit = vec.size();
 for (i = 0; i < limit; ++i) {
  if (vec[i] >= 0.0) {
   if (i != place)
    vec[place] = vec[i];
   ++place;
  }
 }
 vec.resize(place);
}
 


Название: Re: удаление элементов из вектора
Отправлено: Пантер от Сентябрь 14, 2010, 19:31
Ты уверен, что это будет лучше erase?


Название: Re: удаление элементов из вектора
Отправлено: Igors от Сентябрь 14, 2010, 20:12
Ты уверен, что это будет лучше erase?
"лучше" - кому как, но быстрее - намного  :)


Название: Re: удаление элементов из вектора
Отправлено: navrocky от Сентябрь 19, 2010, 12:36
Код
C++ (Qt)
// удаляем все отрицательные элементы
void DeleteNegatives( std::vector<double> & vec )
{
 size_t i, place = 0, limit = vec.size();
 for (i = 0; i < limit; ++i) {
  if (vec[i] >= 0.0) {
   if (i != place)
    vec[place] = vec[i];
   ++place;
  }
 }
 vec.resize(place);
}
 

Это велосипед. Читаем здесь - http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove.

std::remove(_if) переставляет все ненужные элементы в конец списка, std::erase потом их откусывает.

Код:
bool is_negative(int val) { return val < 0; }
...
v.erase(std::remove_if(v.begin(), v.end(), is_negative), v.end());

Этот подход не менее эффективен, чем описанный выше код.


Название: Re: удаление элементов из вектора
Отправлено: Igors от Сентябрь 19, 2010, 14:34
Это велосипед. Читаем здесь - http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove.

std::remove(_if) переставляет все ненужные элементы в конец списка, std::erase потом их откусывает.

Код:
bool is_negative(int val) { return val < 0; }
...
v.erase(std::remove_if(v.begin(), v.end(), is_negative), v.end());

Этот подход не менее эффективен, чем описанный выше код.
Но и не более  :) А что будете делать напр. если удаление зависит от предыдущего(их) элементов? Заметим также что контроля типов remove_if не имеет: Вы написали int вместо double, но компилятор промолчит, элемент -0.5 удален не будет.

По поводу "велосипеда". Читая Ваш пост, можно подумать примерно так: "изобретение велосипеда" есть демонстрация безграмотности/неосведомленности, это нехорошо и даже позорно  :) Что же нужно делать? Да просто "зубрить" (запоминать) больше ф-ций - вот и все. Мне кажется такой подход превращает программирование в утомительную и бесполезную эксплуатацию памяти.

Ваши демонстрации техники STL и template безупречны (в этом и др. постах), но уж очень просты и не очень необходимы  :) А вот как сделать более сложную, а главное - очень нужную template ф-цию?
http://www.prog.org.ru/index.php?topic=14912.msg98504#msg98504 (http://www.prog.org.ru/index.php?topic=14912.msg98504#msg98504)
Welcome  :)