如果不知道具体的场景,即元素保存在什么样的容器中,是不能从序列中移除元素的。因此,“移除元素的”算法也无法做到这一点,它们只会重写被选择的元素或者忽略复制的元素。移除操作不会改变被“移除”元素的序列的元素个数。
有 4 种移除算法:
- remove() 可以从它的前两个正向迭代器参数指定的序列中移除和第三个参数相等的对象。基本上每个元素都是通过用它后面的元素覆盖它来实现移除的。它会返回一个指向新的最后一个元素之后的位置的迭代器。
- remove_copy() 可以将前两个正向迭代器参数指定的序列中的元素复制到第三个参数指定的目的序列中,并忽略和第 4 个参数相等的元素。它返回一个指向最后一个被复制到目的序列的元素的后一个位置的迭代器。序列不能是重叠的。
- remove_if() 可以从前两个正向迭代器指定的序列中移除能够使作为第三个参数的谓词返回 true 的元素。
- remove_copy_if() 可以将前两个正向迭代器参数指定的序列中,能够使作为第 4 个参数的谓词返回 true 的元素,复制到第三个参数指定的目的序列中。它返回一个指向最后一个被复制到目的序列的元素的后一个位置的迭代器。序列不能是重叠的。
本文作者原创,转载请附上文章出处与本文链接。
C++ remove()函数用法详解目录
1 remove
#include <iostream>
#include <deque>
using namespace std;
int main()
{
int i;
deque<double> samples{ 1.5, 2.6, 0.0, 3.1, 0.0, 0.0, 4.1, 0.0, 6.7, 0.0 };
cout << "容器samples : " << endl;
for (i = 0; i < samples.size(); i++)
{
cout << samples[i] << " ";
}
cout << "删除0.0 : " << endl;
samples.erase(remove(begin(samples), end(samples), 0.0), end(samples));
cout << "容器samples : " << endl;
for (i = 0; i < samples.size(); i++)
{
cout << samples[i] << " ";
}
// 1.5 2.6 3.1 4.1 6.7
}
sample 中不应包含为 0 的物理测量值。remove() 算法会通过左移其他元素来覆盖它们,通过这种方式就可以消除杂乱分布的 0。remove() 返回的迭代器指向通过这个操作得到的新序列的尾部,所以可以用它作为被删除序列的开始迭代器来调用 samples 的成员函数 erase()。注释说明容器中的元素没有被改变。
如果想保留原始序列,并生成一个移除选定元素之后的副本,可以使用 remove_copy()
2 remove_copy
#include <iostream>
#include <deque>
#include <vector>
#include <algorithm>
#include <list>
#include <set>
#include <functional>
#include <iterator>
using namespace std;
int main()
{
int i;
deque<double> samples{ 1.5, 2.6, 0.0, 3.1, 0.0, 0.0, 4.1, 0.0, 6.7, 0.0 };
vector<double> edited_samples;
cout << "容器samples : " << endl;
for (i = 0; i < samples.size(); i++)
{
cout << samples[i] << " ";
}
cout << "\n 删除0.0 : " << endl;
//samples.erase(remove(begin(samples), end(samples), 0.0), end(samples));
remove_copy(begin(samples), end(samples), back_inserter(edited_samples), 0.0);
cout << "容器samples : " << endl;
for (i = 0; i < samples.size(); i++)
{
cout << samples[i] << " ";
}
cout << "\n 容器edited_samples : " << endl;
for (i = 0; i < edited_samples.size(); i++)
{
cout << edited_samples[i] << " ";
}
// 1.5 2.6 3.1 4.1 6.7
}
samples 容器中的非零元素会被复制到 edited_samples 容器中,edited_samples 正好是一个 vector 容器。通过 back_insert_iterator 对象将这些元素添加到 edited_samples,因此这个容器只包含从 sample 中复制的元素。
3 remove_if
remove_if() 提供了更强大的能力,它能够从序列中移除和给定值匹配的元素。谓词会决定一个元素是否被移除;它接受序列中的一个元素为参数,并返回一个布尔值。
#include <iostream>
#include <deque>
#include <vector>
#include <algorithm>
#include <list>
#include <set>
#include <functional>
#include <iterator>
using namespace std;
int main()
{
using Name = pair<string, string>; // First and second name
set<Name> blacklist{ Name {"Al", "Bedo"}, Name {"Ann", "Ounce"}, Name {"Jo","King"} };
deque<Name> candidates{ Name{"Stan", "Down"}, Name {"Al", "Bedo"}, Name {"Dan", "Druff"},Name {"Di", "Gress"}, Name {"Ann", "Ounce"}, Name {"Bea", "Gone"} };
candidates.erase(remove_if(begin(candidates), end(candidates), [&blacklist](const Name& name)
{
return blacklist.count(name);
}
), end(candidates));
for_each(begin(candidates), end(candidates), [](const Name& name)
{
cout << '"' << name.first << " " << name.second << "\" ";
}
);
cout << endl; // "Stan Down" "Dan Druff" "Di Gress" "Bea Gone"
}
这段代码可以将candidates容器中关于blacklist容器重复的内容清楚。
4 remove_copy_if
remove_copy_if() 之于 remove_copy(),就像 remove_if() 之于 remove。下面展示它是如何工作的:
#include <iostream>
#include <deque>
#include <vector>
#include <algorithm>
#include <list>
#include <set>
#include <functional>
#include <iterator>
using namespace std;
//有效值获取复制
bool bools(int i) {
//取一个值能被二整除的值
return ((i % 2) == 1);
}
int main()
{
//旧容器
int myattr[] = { 1,2,4,3,8,9,7,5,6,10 };
//创建一个新容器
vector<int> myattring(10);
//将myattr里符合条件的数据拷贝到myattring中
remove_copy_if(myattr, myattr + 10, myattring.begin(), bools);
//用作对比比较
cout << "1 2 4 3 8 9 7 5 6 10" << endl;
cout << endl;
//for循环遍历出所有拷贝值
for (vector<int>::iterator it = myattring.begin(); it != myattring.end(); ++it)
{
cout << *it << ends;
}
}