从向量中删除项目
Posted
技术标签:
【中文标题】从向量中删除项目【英文标题】: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())
【参考方案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));
【讨论】:
另请参阅this code review,了解mem_fn
谓词的一些限制。以上是关于从向量中删除项目的主要内容,如果未能解决你的问题,请参考以下文章