remove_copy/remove 及其泛化版 remove_copy_if/remove_if
这两组函数提供的实现删除序列中的相关元素的思路,对我们实现自己的算法是有帮助的。
这四个函数所在的头文件仍然是#include <algorithm>
。
- remove 需调用 remove_copy 才能实现自身的功能
- remove_if 则需调用 remove_copy_if 实现自身的功能
- remove_if 是 remove 的泛化版本,也即 remove 使用的是“相等(equality)条件”,remove_if 则是根据参数中指定的某一断言(predicate)为条件
尤其需要注意的是,这四个函数虽然函数名都有 remove
,但均没有移除容器元素的动作,也即至少均不改变容器的大小,更有甚者 remove_copy/remove_copy_if 甚至不会对原容器做任何改变。
remove/remove_if 更像是一种对序列的重新整理,将残余元素置于序列的尾部,返回指向第一个残余元素的迭代器,故只需将 remove/remove_if 函数与容器的 erase() 成员函数相结合时,才会真正删除容器中等于某值(remove)或符合某一条件(remove_if)的元素。最后我们会给出一个删除容器中所有偶数的操作。
remove_copy
移除
[first, last)
区间内所有与value
相等的元素,它并不真正从容器中删除那些元素,而是将结果复制(copy)到一个以result
标示起始位置的容器身上(也即可以对原始容器没有任何改变,如果result
不在[first, last)
的区间内)。新容器可以和原容器重叠(remove 便是如此)template<class InputIterator, class OutputIterator, class T> OutputIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value) { for (; first < last; ++first) { if (*first != *result) { *result = *first; ++result; } } return result; }
remove:移除,但不删除,残余元素置于容器的最后
所以很方便
coll.erase(std::remove(...), coll.end())
,真正地移除无关数据。template<class ForwardIterator, class T> ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value) { first = find(first, last, value); ForwardIterator next = first; return first == last ? first : remove_copy(++next, last, first, value); }
remove_copy_if
template<typename InputIterator, typename OutputIterator, typename Pred> OutputIterator remove_copy_if(InputIterator first, InputIterator last, OutputIterator result, Pred pred) { for (; first < last; ++first) { if (!pred(*first)) { *result = *first; ++result; } } return result; }
remove_if
template<typename ForwardIterator, typename Pred>
ForwardIterator remove_if(ForwardIterator first, ForwardIterator last, Pred pred)
{
first = std::find_if(first, last, pred);
ForwardIterator next = first;
return first == last ? first : remove_copy_if(++next, last, first, pred);
// return remove_copy_if(first, last, first, pred);
}
一个实例
移除序列中的偶数
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9};
v.erase(std::remove_if(v.begin(), v.end(), [=](int x){ return x%2 == 0;}), v.end());