现在假设我有一个数据列表,它保存在向量a
中。我要做的是检查数据列表中的每个元素是否满足某些条件。如果是,则会将其从a
中移除,然后保存在另一个向量b
中。例如,在以下代码中,我可以轻松完成此任务:
class findOddClass
{
public:
int Common;
findOddClass(int common):Common(common){};
bool operator()(const int &i)
{
return (i%Common == 1);
}
};
void testFunctionObject()
{
std::vector<int> objArray;
for(int i=0; i<10; i++)
objArray.push_back(i);
findOddClass finder(2);
std::vector<int>::iterator it = objArray.begin();
std::vector<int> oddArray;
while(it != objArray.end())
{
if (finder(*it))
{
oddArray.push_back(*it);
it = objArray.erase(it);
}
else
it++;
}
std::cout<<"Even array"<<std::endl;
for(it=objArray.begin(); it != objArray.end(); it++)
std::cout<<*it<<" ";
std::cout<<std::endl;
std::cout<<"Odd array"<<std::endl;
for(it= oddArray.begin(); it!=oddArray.end(); it++)
std::cout<<*it<<" ";
std::cout<<std::endl;
}
但是,如果我想以更优雅的方式完成相同的任务:
void testFunctionObject()
{
std::vector<int> objArray;
for(int i=0; i<10; i++)
objArray.push_back(i);
std::vector<int>::iterator itEnd;
itEnd = std::remove_if(objArray.begin(),objArray.end(),findOddClass(2));
std::vector<int> oddArray;
std::vector<int>::iterator it = itEnd;
while(it != objArray.end())
{
oddArray.push_back(*it);
it++;
}
objArray.erase(itEnd,objArray.end());
std::cout<<"Even array"<<std::endl;
for(it=objArray.begin(); it != objArray.end(); it++)
std::cout<<*it<<" ";
std::cout<<std::endl;
std::cout<<"Odd array"<<std::endl;
for(it= oddArray.begin(); it!=oddArray.end(); it++)
std::cout<<*it<<" ";
std::cout<<std::endl;
}
它会失败。原因在于std::removal_if
不会保留将被删除的元素的痕迹。我只是想知道STL中是否有功能可以完成这项工作,因此这是一种更优雅的工作方式。谢谢。
答案 0 :(得分:3)
如果你想根据一些谓词将原始序列分成两个序列,我建议使用算法std :: partition_copy。当算法返回一对输出迭代器时,使用前一次调用std :: partition_copy的结果很容易应用方法擦除
template <class InputIterator, class OutputIterator1,
class OutputIterator2, class Predicate>
pair<OutputIterator1, OutputIterator2>
partition_copy(InputIterator first, InputIterator last,
OutputIterator1 out_true, OutputIterator2 out_false,
Predicate pred);
答案 1 :(得分:0)
std::partition
对于可移动元素非常有效。勾勒出来,代码看起来像这样:
auto partition_point = std::partition(v1.begin(), v1.end(), predicate);
// Move the elements at the range to the other vector.
v2.assign(std::make_move_iterator(partition_point),
std::make_move_iterator(v1.end()));
// Remove the remains from the original.
v1.erase(partition_point, v1.end());
优于partition_copy
解决方案的优势在于,实际复制没有进行,这使得std::string
或仅移动类型等类似句柄的事物更有效。