根据索引删除向量元素

7

我想根据索引删除向量中的元素,例如所有偶数索引元素。 我已经了解了erase-remove惯用法,但不知道如何应用它。 这是我的尝试:

    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() );

这会清空整个向量。我希望只删除已由remove算法标记的元素。
然后我尝试了这个方法。
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个回答

10

当你从0size循环时,由于索引会随着元素的删除而改变,因此你最终会跳过一半的元素。请在你的for循环中将范围修改为从size()0

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

}

2
你是不是指的 size() - 1 - Some programmer dude
3
不行,如果size == 0会破坏循环。每当你引用元素时,直接使用[i-1]。 - JosephH
1
for(std::vector<int>::iterator it = line.end(); it != line.begin(); --it) - Mateen Ulhaq
@AusCBloke 不是。它是“unsigned int”的意思,这意味着当“i”为“-1==0xFFFFFFFF=4294967295”时,“i”实际上会大于0,你将进入一个接近无限循环的状态。 - JosephH
@JosephH:哈哈,我错了,没注意到unsigned这个部分,只看到了int。+1。 - AusCBloke
显示剩余3条评论

5

Online Demo:

#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;
}

1
+1. 然而,看起来remove_if是基于元素值来删除元素的。这正确吗?如果我们想要根据它们的索引删除向量元素怎么办? - Alexey
4
正如本杰明·林德利在他对类似问题的回答中所评论的:“这对remove_if应用谓词的顺序做出了一种假设,而这种假设并不被标准文本所保证。” - Tony Delroy

4
为什么不使用 remove_if 函数?在函数内部使用静态变量来表示当前元素的索引。

2
除了上面的答案之外,这个链接中的示例代码正好做到了你(OP)所寻找的功能:http://www.cplusplus.com/reference/algorithm/remove_if/ - yasouser
2
@yasouser,不,它不是基于索引而是基于值(偶数或奇数)来删除项目的示例代码。 - Ton van den Heuvel

1

1

以下是如何使用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;
}

3
我不确定你是否可以根据索引删除元素......这就是问题的关键所在。 - Tony Delroy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接