0

所以我有一个无符号整数向量(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. 在大多数情况下,var是错误的。我想删除所有vector1具有var= true的元素。

我所做的是:

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

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

4

3 回答 3

3

您必须使用erase-remove 习惯用法从向量中删除元素。

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

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

于 2013-02-06T15:45:24.653 回答
1

您可以在循环中保留一个临时向量、副本vector1并对其进行迭代,for然后从vector1.

于 2013-02-06T15:48:19.920 回答
1

您正在擦除向量中的元素,同时对其进行迭代。因此,当擦除一个元素时,您总是会跳过下一个元素,因为您i在刚刚缩短向量的同时增加了i(如果您使用适当的迭代器循环而不是索引循环,情况会更糟)。做到这一点的最好方法是将两个操作分开,首先“标记”(或更确切地说是重新排序)要删除的元素,然后从向量中删除它们。

在实践中,最好使用擦除删除惯用语( vector.erarse(std::remove(...), vector.end())) 来完成,它首先使用std::remove(_if)在开头使用未删除元素重新组织数据并返回范围的新结尾,然后可以使用它来真正删除那些已删除的元素范围内的元素(实际上只是缩短了整个向量),使用std::vector::erase. 使用 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顺便说一句,如果你真的需要而不是仅仅[]记住两者的含义(特别是前者的开销和后者的“可能不安全” ),请务必确定。

于 2013-02-06T16:49:28.997 回答