Удалить векторные элементы на основе индекса - PullRequest
5 голосов
/ 08 декабря 2011

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

    vector<int> line;
    line.reserve(10);
    for(int i=0;i<10;++i)
    {
      line.push_back(i+1);
    }
    for(unsigned int i=0;i<line.size();++i)
    {
      //remove the even indexed elements
      if(i%2 == 0)
      {
        remove(line.begin(),line.end(),line[i]);
      }
    }
line.erase( line.begin(),line.end() );

Это стирает весь вектор. Я надеялся удалить только те элементы, которые были помечены алгоритмом удаления.

Тогда я попробовал это

for(unsigned int i=0;i<line.size();++i)
    {
      //remove the even indexed elements
      if(i%2 == 0)
      {
        line.erase( remove(line.begin(),line.end(),line[i]),line.end() );
      }
    }

Это опять не работает, так как при удалении возникает проблема, индексы, похоже, сдвигаются при переборе по вектору. Какой должен быть правильный подход для достижения этой цели.

Ответы [ 5 ]

8 голосов
/ 08 декабря 2011

Переходя от 0 к size, вы в конечном итоге пропустите половину элементов, потому что индексы меняются при удалении элементов. Сделайте ваш for цикл из size() в 0:

for(unsigned int i = line.size(); i > 0; i--)
{

}
6 голосов
/ 08 декабря 2011

Демоверсия :

#include <vector> 
#include <algorithm>
#include <iostream>

/*Check if Index is Even or Odd*/ 
bool is_IndexEven(int i) 
{
   static int k = 1;

   /*Handle Index 0 as special case as per choice*/
   if(k == 1)
   {
       k++;
       return false;
   } 

   if(k++ % 2)
       return true;
   else 
       return false; 
 }

int main() 
{
    using namespace std;
    int elements[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    // create a vector that holds the numbers from 0-9.
    vector<int> v(elements, elements + 10); 

    /*Display elements before removal*/    
    vector<int>::const_iterator iter = v.begin();
    cout<<"Before\n";

    for(iter;iter!= v.end();++iter)
    {
        cout<<*iter;
    }

    /*Remove_if + Erase Algorithm for one step removal*/
    v.erase( remove_if(v.begin(), v.end(), is_IndexEven), v.end() ); 

    /*Display result after elements removed*/
    cout<<"\nAfter\n";
    iter = v.begin();
    for(iter;iter!= v.end();++iter)
    {
       cout<<*iter;
    }

    return 0;
}
4 голосов
/ 08 декабря 2011

Почему бы вам не использовать remove_if ?Используйте статическую переменную внутри функции, чтобы сигнализировать индекс для текущего элемента.

1 голос
/ 16 января 2014

Ответ, обобщающий не только тип контейнера, который должен быть обработан, но и тип контейнера, в котором содержатся удаляемые индексы, дан в: Стирание элементов в stl :: vector с использованием индексов

1 голос
/ 08 декабря 2011

Вот как использовать метод erase-remove для удаления нечетных чисел из вектора.Я не уверен, можете ли вы удалять элементы на основе индекса, потому что remove_if () применяет предикат к значениям, указанным итераторами, а не сам итератор.

См. Следующее: http://cplusplus.com/reference/algorithm/remove_if/

#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
using namespace std;

int main()
{
    vector<int> v;
    v.push_back(11);
    v.push_back(22);
    v.push_back(33);
    v.push_back(44);
    v.push_back(55);
    v.push_back(66);
    v.push_back(77);
    ostream_iterator<int> printit(cout, " ");

    cout << "Before removing odd numbers" << endl;
    copy(v.begin(), v.end(), printit);


    v.erase(remove_if(v.begin(), v.end(),
          [] (int e) { return e%2 == 1; }), v.end());

    cout << endl;
    cout << "After removing odd numbers" << endl;
    copy(v.begin(), v.end(), printit);
    cout << endl;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...