擦除矢量中的元素

时间:2013-02-06 15:41:49

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

所以我有一个无符号整数的向量(vector<unsigned int>被称为vector1)。我有另一个我创建的结构的向量(vector<struct>被称为vector2)。 vector<int>包含一个整数,它是vector<struct>的索引。例如,让我们说vector<int = {5, 17, 18, 19}。这意味着vector2.at(5) == vector2.at(vector1.at(0))

在结构中,我有一个名为var的bool变量。在大多数情况下,var是错误的。我想删除vector1var = true的所有元素。

我做的是:

for (unsigned int i = 0; i < vector1.size(); i++)
{
   if (vector2.at(vector1.at(i)).var)
    vector1.erase(vector.begin() + i);
}

唯一的问题是它不会删除所有真正的元素。我已经多次运行for循环以删除所有值。这是正确的行为吗?如果不是,我哪里出错?

3 个答案:

答案 0 :(得分:3)

您必须使用erase-remove idiom删除矢量中的元素。

v.erase(std::remove(v.begin(), v.end(), value), v.begin);

std::remove将元素移动到向量的末尾,erase将从向量中删除元素。

答案 1 :(得分:1)

您可以保留vector1的临时向量,副本并在for循环中对其进行迭代,然后从vector1删除。

答案 2 :(得分:1)

您正在擦除向量中的元素,同时迭代它。因此,当擦除一个元素时,你总是跳过下一个元素,因为你在i处缩短了向量时增加了i(如果你使用了一个正确的迭代器循环而不是索引循环)。执行此操作的最佳方法是分离两个opretions,首先“标记”(或者更确切地说,重新排序)要删除的元素,然后从向量中删除它们。

这实际上最好使用erase-remove idiomvector.erarse(std::remove(...), vector.end()))完成,该std::remove(_if)首先使用std::vector::erase重新组织数据,并在开头使用未删除的元素并返回新结尾范围的,然后可以用来真正删除范围内的那些被删除的元素(实际上只是缩短整个向量),使用{{3}}。使用C ++ 11 lambda,可以很容易地表达删除条件:

vector1.erase(std::remove_if(                        //erase range starting here
                  vector1.begin(), vector1.end(),    //iterate over whole vector
                  [&vector2](unsigned int i)         //call this for each element
                      { return vector2.at(i).var; }),  //return true to remove
              vector1.end());                        //erase up to old end

编辑顺便说一句,一如既往地确定您是否真的需要std::vector::at而不仅仅是[]并牢记两者的含义(特别是前者的开销和后者的“也许不安全”