【问题标题】:Removing items from a vector从向量中删除项目
【发布时间】:2014-05-24 18:44:53
【问题描述】:

我正在寻找从向量中删除多个项目的最有效方法?

基本上,我将在向量中搜索一个标志并删除具有该标志的对象。

但是,我听说从向量中擦除对象会弄乱您的迭代器,那么循环遍历向量(可能包含数千个对象)并删除带有特定标志的对象的最有效方法是什么?

我希望不必多次循环遍历向量。

【问题讨论】:

  • std::remove_if.
  • 如何不弄乱迭代器:iterator = vector.erase(iterator);
  • 向量中项目的顺序是否重要?如果没有,每当您遇到要删除的向量中的项目时,将该项目设置为等于向量中的最后一项,然后在向量上调用 pop_back()。通过这样做,您可以在 O(N) 时间内从向量中删除任意数量的项目。 (请注意,它确实会改变项目的顺序,所以如果这是一个问题,请改用 std::remove_if())

标签: c++ performance vector


【解决方案1】:

如果有多个元素匹配标志你应该使用std::remove_if():

vec.erase(std::remove_if(vec.begin(), v.end(), [](T const& e){ return e.flag(); }),
          v.end());

使用这种方法,每个向量元素最多移动一次。删除单个元素可能会移动每个元素O(n) 次。

【讨论】:

  • 我不确定“up to O(n)”是否是一个合理的表达方式。 O(n) 已经意味着“最多”...
  • 干杯,太完美了:)
  • 它怎么能移动每个元素一次,还要O(n)次?
  • @soandos:例如,假设您从序列中删除第一个 n/2 元素,一次一个元素。您将移动每个后半部分元素n/2 次。
  • 那么“使用这种方法最多移动每个向量元素一次”是什么意思?您的意思是删除吗?
【解决方案2】:

std::remove_if 算法有时可以与其他实用程序优雅地结合使用。例如,如果您的课程如下所示:

struct Foo
{
    bool flag;               // either this...
    bool get_flag() const;   // ... or this
    // ...
};

那么你可以使用std::mem_fn来生成一个访问器函子,分别返回成员的值或者调用成员函数:

std::mem_fn(&Foo::flag)
std::mem_fn(&Foo::get_flag)

最后,您可以使用参数相关查找来依赖命名空间std,只要其中一个参数类型来自该命名空间即可找到。例如:

#include <algorithm>   // for remove_if
#include <functional>  // for mem_fn
#include <iterator>    // for begin, end
#include <vector>      // for vector

std::vector<Foo> v = /* something */ ;

v.erase(remove_if(begin(v), end(v), std::mem_fn(&Foo::flag)), end(v));

【讨论】:

猜你喜欢
  • 2021-11-08
  • 1970-01-01
  • 1970-01-01
  • 2019-08-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多