Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是否支持C++/用于按属性对对象进行排序的STL?_C++_Sorting_Stl_Attributes - Fatal编程技术网

C++ 是否支持C++/用于按属性对对象进行排序的STL?

C++ 是否支持C++/用于按属性对对象进行排序的STL?,c++,sorting,stl,attributes,C++,Sorting,Stl,Attributes,我想知道STL中是否支持这一点: 假设我有这样一门课: class Person { public: int getAge() const; double getIncome() const; .. .. }; 和一个向量: vector<Person*> people; 矢量人; 我想按年龄对人群进行分类: 我知道我可以通过以下方式完成: class AgeCmp { public: bool operator() ( const Person* p1,

我想知道STL中是否支持这一点:

假设我有这样一门课:

class Person
{
public:
  int getAge() const;
  double getIncome() const;
  ..
  ..
};
和一个向量:

vector<Person*> people;
矢量人;
我想按年龄对人群进行分类: 我知道我可以通过以下方式完成:

class AgeCmp
{
public:
   bool operator() ( const Person* p1, const Person* p2 ) const
   {
     return p1->getAge() < p2->getAge();
   }
};
sort( people.begin(), people.end(), AgeCmp() );
class-AgeCmp
{
公众:
布尔运算符()(常数人*p1,常数人*p2)常数
{
返回p1->getAge()getAge();
}
};
排序(people.begin()、people.end()、AgeCmp());
有没有一种不那么冗长的方法?仅仅因为我想基于“属性”进行排序,就必须定义一个完整的类,这似乎有些过分。也许是这样的

sort( people.begin(), people.end(), cmpfn<Person,Person::getAge>() );
sort(people.begin()、people.end()、cmpfn());

如果您只想根据一件事对人员进行排序(或者如果您想在大多数时间使用合理的默认值),则覆盖
运算符您可以只使用全局函数或静态函数。这些全局或静态函数中的每一个都与一个属性进行比较。不需要上课。保存参数进行比较的一种方法是使用boost-bind,但bind仅用于查找所有类或将所有类与某个绑定参数进行比较。跨多个元素存储数据是生成函子的唯一原因


编辑:另请参见boost lambda函数,但它们仅适用于简单函数。

您不需要创建类,只需编写函数即可:

#include <vector>
#include <algorithm>
using namespace std;

struct Person {
    int age;
    int getage() const {
        return age;
    }
};

bool cmp( const Person * a, const Person * b ) {
    return a->getage() < b->getage() ;
}

int main() {
    vector <Person*> v;
    sort( v.begin(), v.end(), cmp );
}
#include <functional>

template <class Object, class ResultType>
class CompareAttributeT: public std::binary_function<const Object*, const Object*, bool>
{
    typedef ResultType (Object::*Getter)() const;
    Getter getter;
public:
    CompareAttributeT(Getter method): getter(method) {}
    bool operator()(const Object* lhv, const Object* rhv) const
    {
        return (lhv->*getter)() < (rhv->*getter)();
    }
};

template <class Object, class ResultType>
CompareAttributeT<Object, ResultType> CompareAttribute(ResultType (Object::*getter)() const)
{
    return CompareAttributeT<Object, ResultType>(getter);
}
#包括
#包括
使用名称空间std;
结构人{
智力年龄;
int getage()常量{
回归年龄;
}
};
布尔cmp(常数人*a,常数人*b){
返回a->getage()getage();
}
int main(){
向量v;
排序(v.begin(),v.end(),cmp);
}

基于成员属性进行比较的通用适配器。虽然它在第一次可重用时更加冗长

// Generic member less than
template <typename T, typename M, typename C>
struct member_lt_type 
{
   typedef M T::* member_ptr;
   member_lt_type( member_ptr p, C c ) : ptr(p), cmp(c) {}
   bool operator()( T const & lhs, T const & rhs ) const 
   {
      return cmp( lhs.*ptr, rhs.*ptr );
   }
   member_ptr ptr;
   C cmp;
};

// dereference adaptor
template <typename T, typename C>
struct dereferrer
{
   dereferrer( C cmp ) : cmp(cmp) {}
   bool operator()( T * lhs, T * rhs ) const {
      return cmp( *lhs, *rhs );
   }
   C cmp;
};

// syntactic sugar
template <typename T, typename M>
member_lt_type<T,M, std::less<M> > member_lt( M T::*ptr ) {
   return member_lt_type<T,M, std::less<M> >(ptr, std::less<M>() );
}

template <typename T, typename M, typename C>
member_lt_type<T,M,C> member_lt( M T::*ptr, C cmp ) {
   return member_lt_type<T,M,C>( ptr, cmp );
}

template <typename T, typename C>
dereferrer<T,C> deref( C cmp ) {
   return dereferrer<T,C>( cmp );
}

// usage:    
struct test { int x; }
int main() {
   std::vector<test> v;
   std::sort( v.begin(), v.end(), member_lt( &test::x ) );
   std::sort( v.begin(), v.end(), member_lt( &test::x, std::greater<int>() ) );

   std::vector<test*> vp;
   std::sort( v.begin(), v.end(), deref<test>( member_lt( &test::x ) ) );
}
//泛型成员小于
模板
结构成员类型
{
类型定义M T::*成员;
成员类型(成员类型p,cc):ptr(p),cmp(C){}
布尔运算符()
{
返回cmp(左侧。*ptr,右侧。*ptr);
}
成员(ptr ptr),;
C化学机械抛光;
};
//解引用适配器
模板
结构解除器
{
德里费雷尔(cmp):cmp(cmp){
布尔运算符()(T*lhs,T*rhs)常量{
返回cmp(*左侧,*右侧);
}
C化学机械抛光;
};
//句法糖
模板
成员类型成员(M T::*ptr){
返回成员类型(ptr,std::less());
}
模板
成员类型成员(M T::*ptr,C cmp){
返回成员类型(ptr、cmp);
}
模板
dereferrer deref(C cmp){
返回去铁器(cmp);
}
//用法:
结构测试{int x;}
int main(){
std::向量v;
std::sort(v.begin()、v.end()、member_lt(&test::x));
std::sort(v.begin(),v.end(),member_lt(&test::x,std::greater());
std::向量vp;
std::sort(v.begin()、v.end()、deref(member_lt(&test::x));
}

我看到dribeas已经发布了这个想法,但既然我已经编写了它,下面是如何编写一个通用的比较器来使用getter函数

#include <functional>

template <class Object, class ResultType>
class CompareAttributeT: public std::binary_function<const Object*, const Object*, bool>
{
    typedef ResultType (Object::*Getter)() const;
    Getter getter;
public:
    CompareAttributeT(Getter method): getter(method) {}
    bool operator()(const Object* lhv, const Object* rhv) const
    {
        return (lhv->*getter)() < (rhv->*getter)();
    }
};

template <class Object, class ResultType>
CompareAttributeT<Object, ResultType> CompareAttribute(ResultType (Object::*getter)() const)
{
    return CompareAttributeT<Object, ResultType>(getter);
}

我认为对非指针重载
运算符()
可能是个好主意,但这样一来,就无法通过继承
二进制函数来定义参数类型了,这可能不是一个很大的损失,因为在需要这些参数的地方使用它会很困难,例如,无论如何,我们都无法否定比较函子。

这与其说是一个答案本身,不如说是对阿拉克对我的评论的回答,即用函数而不是函子排序会更慢。下面是一些比较各种排序的测试代码(当然很难看——CnP太多了):qsort、std::sort of vector vs.array和std::sort使用模板类、模板函数或普通函数进行比较:

#include <vector>
#include <algorithm>
#include <stdlib.h>
#include <time.h>

int compare(void const *a, void const *b) {
    if (*(int *)a > *(int *)b)
        return -1;
    if (*(int *)a == *(int *)b)
        return 0;
    return 1;
}

const int size = 200000;

typedef unsigned long ul;

void report(char const *title, clock_t ticks) { 
    printf("%s took %f seconds\n", title, ticks/(double)CLOCKS_PER_SEC);
}

void wait() { 
    while (clock() == clock())
        ;
}

template <class T>
struct cmp1 { 
    bool operator()(T const &a, T const &b) { 
        return a < b;
    }
};

template <class T>
bool cmp2(T const &a, T const &b) { 
    return a<b;
}

bool cmp3(int a, int b) { 
    return a<b;
}

int main(void) {
    static int array1[size];
    static int array2[size];

    srand(time(NULL));

    for (int i=0; i<size; i++) 
        array1[i] = rand();

    const int iterations = 100;

    clock_t total = 0;

    for (int i=0; i<iterations; i++) { 
        memcpy(array2, array1, sizeof(array1));
        wait();
        clock_t start = clock();
        qsort(array2, size, sizeof(array2[0]), compare);
        total += clock()-start;
    }
    report("qsort", total);

    total = 0;
    for (int i=0; i<iterations; i++) {
        memcpy(array2, array1, sizeof(array1));
        wait();
        clock_t start = clock();
        std::sort(array2, array2+size);
        total += clock()- start;
    }
    report("std::sort (array)", total);

    total = 0;
    for (int i=0; i<iterations; i++) {
        memcpy(array2, array1, sizeof(array1));
        wait();
        clock_t start = clock();
        std::sort(array2, array2+size, cmp1<int>());
        total += clock()- start;
    }
    report("std::sort (template class comparator)", total);

    total = 0;
    for (int i=0; i<iterations; i++) {
        memcpy(array2, array1, sizeof(array1));
        wait();
        clock_t start = clock();
        std::sort(array2, array2+size, cmp2<int>);
        total += clock()- start;
    }
    report("std::sort (template func comparator)", total);

    total = 0;
    for (int i=0; i<iterations; i++) {
        memcpy(array2, array1, sizeof(array1));
        wait();
        clock_t start = clock();
        std::sort(array2, array2+size, cmp3);
        total += clock()- start;
    }
    report("std::sort (func comparator)", total);

    total = 0;
    for (int i=0; i<iterations; i++) {
        std::vector<int> array3(array1, array1+size);
        wait();
        clock_t start = clock();
        std::sort(array3.begin(), array3.end());
        total += clock()-start;
    }
    report("std::sort (vector)", total);

    return 0;
} 
我相信这些可以很清楚地分为三类:使用带有默认比较的sort和使用template类生成最快的代码。使用函数或模板函数显然较慢。使用qsort是(令人惊讶的是)最慢的,大约是2:1


cmp2和cmp3之间的差异似乎完全源于通过引用传递与通过值传递——如果您将cmp2更改为通过值获取其参数,则其速度与cmp3完全匹配(至少在我的测试中是这样)。不同之处在于,如果您知道类型将是
int
,您几乎肯定会按值传递,而对于泛型
T
,您通常会按常量引用传递(以防万一它的复制成本更高)。

我只是根据Uncleben和david rodriguez Dribea的想法尝试了这个方法

这似乎在我当前的编译器中起作用。g++3.2.3。请让我知道它是否适用于其他编译器

#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

class Person
{
public:
    Person( int _age )
        :age(_age)
    {
    }
    int getAge() const { return age; }
private:
    int age;
};

template <typename T, typename ResType>
class get_lt_type
{
    ResType (T::*getter) () const;
public:
    get_lt_type(ResType (T::*method) () const ):getter(method) {}
    bool operator() ( const T* pT1, const T* pT2 ) const
    {
        return (pT1->*getter)() < (pT2->*getter)();
    }
};

template <typename T, typename ResType>
get_lt_type<T,ResType> get_lt( ResType (T::*getter) () const ) {
    return get_lt_type<T, ResType>( getter );
}

int main() {
    vector<Person*> people;
    people.push_back( new Person( 54 ) );
    people.push_back( new Person( 4 ) );
    people.push_back( new Person( 14 ) );

    sort( people.begin(), people.end(), get_lt( &Person::getAge) );

    for ( size_t i = 0; i < people.size(); ++i )
    {
        cout << people[i]->getAge() << endl;
    }
    // yes leaking Persons
    return 0;
}
#包括
#包括
#包括
使用名称空间std;
班主任
{
公众:
个人(国际年龄)
:年龄
{
}
int getAge()常量{return age;}
私人:
智力年龄;
};
模板
类获取\u lt\u类型
{
重新键入(T::*getter)()常量;
公众:
get_lt_type(ResType(T::*method)()const):getter(method){
布尔运算符()(常数T*pT1,常数T*pT2)常数
{
返回(pT1->*getter)(<(pT2->*getter)();
}
};
模板
get_lt_type get_lt(ResType(T::*getter))常量){
返回get\u lt\u类型(getter);
}
int main(){
媒介人;
人。推回(新的人(54));
人。推回(新的人(4));
人。推回(新的人(14));
排序(people.begin()、people.end()、get\lt(&Person::getAge));
对于(size_t i=0;icout getAge()这些答案都非常详细,尽管我喜欢模板的想法!只需使用lambda函数,它会让事情变得简单得多

你可以用这个:

sort( people.begin(), people.end(), []( Person a, Person b ){ return a.age < b.age; } );
排序(people.begin(),people.end(),[](persona,personb){返回a.age
对向量进行排序
sort( people.begin(), people.end(), []( Person a, Person b ){ return a.age < b.age; } );