向量使用迭代器擦除特定索引(不基于范围或条件)

时间:2016-05-09 22:49:16

标签: c++ vector erase erase-remove-idiom

说,我在代码中有两个向量,我想在向量“data”中使用迭代器擦除由向量“index_to_filter”索引的元素。代码中的虚拟方式只是指出明显的错误。到目前为止,我无法让它工作,也不知道这是否可能是 erase-remove-idiom?。有没有办法让我错过它?

THX。

#include <iostream>
#include <vector>

int main()
{

std::vector<int> data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::vector<int> index_to_filter{ 1, 5, 8 };

/* needed result data = { 0, 2, 3, 4, 6, 7, 9 }*/

std::vector<int>::iterator iter = index_to_filter.begin();
while (iter != index_to_filter.end())
{
    std::vector<int>::iterator iter_data = data.begin() + *iter;
    iter_data = data.erase(iter_data);
    iter++;
}
/* Throws : vector erase iterator outside range */

for (int i: data)
    std::cout << i << std::endl;

system("pause");
return 0;
}

PS:vector.erase问题在这里被滥用了数十次,但没有找到这个问题的线索!

PS:不欢迎使用迭代器的解决方案。 (没有冒犯!)

感谢

2 个答案:

答案 0 :(得分:5)

你的问题非常简单:

std::vector<int> index_to_filter{ 1, 5, 8 };

你的目的是从另一个数组中删除元素#1,#5和#8,然后从元素#1开始:

Value    0 1 2 3 4 5 6 7 8 9
Index    0 1 2 3 4 5 6 7 8 9
           ^       ^     ^

底线,&#34;索引&#34; line,是向量的索引。顶线,&#34;值&#34; line,是向量中该位置的值。当你开始时,这两个值是相同的。

插入符号标记您要删除的索引,并从元素#1开始。

你忽略的基本差距是当你从矢量中移除一个元素时,你并没有一个间隙的黑洞,那个位置的空洞。容器中的所有后续值都会转移。因此,当您删除元素#1时,剩余的值会移位:

Value    0 2 3 4 5 6 7 8 9
Index    0 1 2 3 4 5 6 7 8
                   ^     ^

您要删除的下一个元素是元素#5。不幸的是,向量中该位置的值不再是5.它是6,因为数组已经移位。您的代码比继续执行并删除索引位置#5,其结果如下:

Value    0 2 3 4 5 7 8 9
Index    0 1 2 3 4 5 6 7
                         ^

你已经离开这里了。但现在,您的代码尝试删除不再存在的索引#8,因为该向量现在更短。一旦你的代码尝试这样做,你就会爆炸。

因此,总而言之:您所缺少的是一个简单的事实,即从向量的中间移除一个值会将所有后续值向上移动一个位置,以填充从被移除的元素留下的间隙,你编写的代码无法解释这一点。

最简单的解决方案是将元素从最高索引位置移除到最低位置。在您的代码中,您已经按排序顺序排列index_to_filter,因此不是从index_to_filter的开头到结尾,从最低到最高的索引进行迭代,而是从{的最后一个索引向后迭代。 {1}}到第一个,所以你的代码试图删除索引8,5,然后是1,这样每次删除元素都不会影响较低的索引位置。

答案 1 :(得分:1)

如果保证index_to_filter被排序,您应该能够以相反的顺序删除元素 - 只要没有删除先前的条目,过滤的索引仍然是正确的。

因此,只需在当前代码中调用index_to_filter.rbegin()index_to_filter.rend()即可。