按照状态排列向量中的元素

时间:2011-10-10 20:41:30

标签: c++ boost

让我们简化一下课程:

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();

我需要一些优雅的解决方案来重新排列(排序)向量中的元素,以便未修改的对象将在序列的开头进行分组。

4 个答案:

答案 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();
}

我们只是不在乎当两者都脏或两者都不脏时会发生什么。