dyn*_*mic 7 c++ vector remove-if
我想使用remove_if函数从向量中删除元素,但将擦除限制为N个元素.
例:
// predicate function that determines if a value is an odd number.
bool IsOdd (int i) {
if (we deleted more than deleteLimit)
return false;
return ((i%2)==1);
}
void otherFunc(){
int deleteLimit = 10;
// remove odd numbers:
std::vector<int>::iterator newEnd =
std::remove_if (myints.begin(), myints.end(), IsOdd (how to pass deleteLimit?) );
}
Run Code Online (Sandbox Code Playgroud)
我需要IsOdd谓词存储它已删除的元素数量以及我们要删除的元素数量.唯一的方法是使用全局变量?像这样:
int deleteLimit = 10;
int removedSoFar = 0;
bool IsOdd (int i) {
if (deleteLimit < removedSoFar)
return false;
if (i%2==1) {
removedSoFar++
return true;
}
return false;
}
remove_if ...
Run Code Online (Sandbox Code Playgroud)
lee*_*mes 11
告诉"到目前为止已删除了多少元素"的状态应该在函数/算法调用之外定义.这是因为仿函数不应该具有在被调用时被修改的状态(这将是未定义的行为).
您应该在仿函数的构造函数中引用此状态(计数器)(或通过lambda中的引用捕获),以便您可以访问和修改此计数器.当这个函子现在被复制,它并不重要的一个是由算法调用,因为所有的人现在持有的参照相同的状态.
使用仿函数(C++ 03):
class IsOdd {
int deleteLimit;
int & deletedSoFar;
public:
IsOdd(int deleteLimit, int & deletedSoFar) :
deleteLimit(deleteLimit), deletedSoFar(deletedSoFar)
{}
bool operator()(int i) const {
if (deletedSoFar < deleteLimit && i % 2) {
++deletedSoFar;
return true;
}
return false;
}
};
int deletedSoFar = 0;
int deleteLimit = 10;
std::remove_if (myints.begin(), myints.end(), IsOdd(deleteLimit, deletedSoFar));
Run Code Online (Sandbox Code Playgroud)
使用lambda(C++ 11):
int deletedSoFar = 0;
int deleteLimit = 10;
auto it = std::remove_if (myints.begin(), myints.end(), [deleteLimit,&deletedSoFar](int i){
if (deletedSoFar < deleteLimit && i % 2) {
++deletedSoFar;
return true;
}
return false;
});
myints.erase(it, myints.end());
Run Code Online (Sandbox Code Playgroud)
除了创建自己的函子之外,您还可以传递一个 lambda 表达式:
auto deleteLimit = 25;
auto removedSoFar = 0;
auto it = remove_if (myints.begin(),
myints.end(),
[deleteLimit, &removedSoFar](int i)->bool
{
if ( (deletedSoFar < deleteLimit) && (i % 2)) {
++deletedSoFar;
return true;
}
return false;
} );
// really remove the elements from the container
myints.erase(it, myints.end());
Run Code Online (Sandbox Code Playgroud)
但是,请注意有状态函子和标准库算法并不总是很好的组合。在这里,对 lambda 的调用可能会产生副作用,因此您无法保证序列中的哪些元素将被删除。
请注意对std::vector::erase. 这是真正从容器中删除不需要的元素所必需的。请参阅擦除删除成语。