让我们简化一下课程:
class A
{
bool val_;
public:
A() : val_(true) {}
bool isNew() const { return val_; }
void setDirty() { val_ = false; }
};
以及此类对象的向量:
vector<A> coll;
coll.push_back(A());
coll.push_back(A());
coll.push_back(A());
coll.push_back(A());
coll[1].setDirty();
coll[3].setDirty();
我需要一些优雅的解决方案来重新排列(排序)向量中的元素,以便未修改的对象将在序列的开头进行分组。
答案 0 :(得分:6)
您可以使用标准库中的Partition算法:
bool MyPredicate(A& a) { return a.isNew();}
...
// bound is iterator pointing to the first element for which predicate returns false
vector<A>::iterator bound = partition(coll.begin(), coll.end(), MyPredicate);
或者,正如Christian Rau建议的解决方案没有单独的功能:
std::partition(coll.begin(), coll.end(), std::mem_fun_ref(&A::isNew))
答案 1 :(得分:2)
sort
:
#include <algorithm>
std::sort(coll.begin(), coll.end(),
[](const A & a, const A & b) -> bool { return a.isNew() < b.isNew(); } );
您必须重写该类才能将isNew()
声明为const
。
对于较旧的编译器,请使用函数而不是lambda:
bool isNewCompare(const A & a, const A & b) { return a.isNew() < b.isNew(); }
std::sort(coll.begin(), coll.end(), isNewCompare);
编辑: @Vladimir有更好的答案,std::partition()
是更适合此问题的算法。
答案 2 :(得分:0)
std::sort
允许您提供自定义比较功能对象。您定义了一个覆盖paranthesis运算符的类,如果第一个参数应该在右参数之前,则返回true:
class COrderByDirty
{
bool operator(const A& lhs, const A& rhs) const
{
// Says lhs should come before rhs only if
// lhs is marked as dirty, and rhs is not
if (lhs.GetDirty() < rhs.Dirty())
{
return true;
}
}
}
然后简单地实例化它用它来排序:
std::sort(coll.begin(), coll.end(), COrderByDirty());
如果你可以使用C ++ 11,你可以避免冗长的类创建并使用lambda,正如Kernek在他的回答中所做的那样。
答案 3 :(得分:0)
您可以使用std::sort
中的<algorithm>
和boost::bind
。它可能看起来像这样:
std::sort(coll.begin(), coll.end(), boost::bind(&A::isDirty, _1));
假设A
有一个函数bool A::isDirty() const
。
这是有效的,因为您隐式使用以下排序谓词:
bool cmp(const A &a, const A &b) {
return a.isDirty();
}
我们只是不在乎当两者都脏或两者都不脏时会发生什么。