按状态排列向量中的元素

Arranging elements in a vector by their status

本文关键字:元素 向量 状态 排列      更新时间:2023-10-16

让我们简化一下class:

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

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

您可以使用标准库中的分区算法:

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

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()是更适合这个问题的算法。

std::sort允许您提供自定义比较函数对象。您定义了一个类,该类覆盖了括号操作符,如果第一个参数应该在右参数之前,则返回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在他的回答中所做的。

您可以将<algorithm>中的std::sortboost::bind一起使用。它可以看起来像这样:

std::sort(coll.begin(), coll.end(), boost::bind(&A::isDirty, _1));

假设Abool A::isDirty() const函数。

这样做是因为您隐式地使用了以下排序谓词:

bool cmp(const A &a, const A &b) {
    return a.isDirty();
}

我们只是不关心两个都是脏的或者两个都不是脏的。