通过对象的属性对对象的矢量进行排序

s00*_*can 10 c++ sorting std

我正在为学校做一个项目,需要对一些数据进行排序.我已经获得了一个对象向量,我必须根据它们的一个属性对对象(就地或使用索引)进行排序.有几个不同的对象和几个不同的属性可以按其排序.这样做的最佳方法是什么?

Eri*_*rik 17

使用std::sort和仿函数.例如:

struct SortByX
{
   bool operator() const (MyClass const & L, MyClass const & R) { return L.x < R.x; }
};

std::sort(vec.begin(), vec.end(), SortByX());
Run Code Online (Sandbox Code Playgroud)

如果L小于R,则对于所需的排序顺序,仿函数的operator()应该返回true.


ild*_*arn 13

有几个不同的对象和几个不同的属性可以按其排序.

虽然Erik发布的解决方案是正确的,但是这个声明让我觉得如果你实际上计划在同一个程序中以多种方式对多个类的多个公共数据成员进行排序,那么它最好是不切实际的,因为每个排序方法都需要它自己的仿函数类型.

我推荐以下抽象:

#include <functional>

template<typename T, typename M, template<typename> class C = std::less>
struct member_comparer : std::binary_function<T, T, bool>
{
    explicit member_comparer(M T::*p) : p_(p) { }

    bool operator ()(T const& lhs, T const& rhs) const
    {
        return C<M>()(lhs.*p_, rhs.*p_);
    }

private:
    M T::*p_;
};

template<typename T, typename M>
member_comparer<T, M> make_member_comparer(M T::*p)
{
    return member_comparer<T, M>(p);
}

template<template<typename> class C, typename T, typename M>
member_comparer<T, M, C> make_member_comparer2(M T::*p)
{
    return member_comparer<T, M, C>(p);
}
Run Code Online (Sandbox Code Playgroud)

用法如下:

#include <algorithm>
#include <vector>
#include <string>

struct MyClass
{
    int i;
    std::string s;

    MyClass(int i_, std::string const& s_) : i(i_), s(s_) { }
};

int main()
{
    std::vector<MyClass> vec;
    vec.push_back(MyClass(2, "two"));
    vec.push_back(MyClass(8, "eight"));

    // sort by i, ascending
    std::sort(vec.begin(), vec.end(), make_member_comparer(&MyClass::i));
    // sort by s, ascending
    std::sort(vec.begin(), vec.end(), make_member_comparer(&MyClass::s));
    // sort by s, descending
    std::sort(vec.begin(), vec.end(), make_member_comparer2<std::greater>(&MyClass::s));
}
Run Code Online (Sandbox Code Playgroud)

这适用于具有公共数据成员的任何类型,如果您需要以多种不同的方式对类进行排序,则可以节省大量的输入.

以下是与公共成员函数而不是公共数据成员一起使用的变体:

#include <functional>

template<typename T, typename M, template<typename> class C = std::less>
struct method_comparer : std::binary_function<T, T, bool>
{
    explicit method_comparer(M (T::*p)() const) : p_(p) { }

    bool operator ()(T const& lhs, T const& rhs) const
    {
        return C<M>()((lhs.*p_)(), (rhs.*p_)());
    }

private:
    M (T::*p_)() const;
};

template<typename T, typename M>
method_comparer<T, M> make_method_comparer(M (T::*p)() const)
{
    return method_comparer<T, M>(p);
}

template<template<typename> class C, typename T, typename M>
method_comparer<T, M, C> make_method_comparer2(M (T::*p)() const)
{
    return method_comparer<T, M, C>(p);
}
Run Code Online (Sandbox Code Playgroud)

使用方式如下:

#include <algorithm>
#include <vector>
#include <string>

class MyClass
{
    int i_;
    std::string s_;

public:
    MyClass(int i, std::string const& s) : i_(i), s_(s) { }

    int i() const { return i_; }
    std::string const& s() const { return s_; }
};

int main()
{
    std::vector<MyClass> vec;
    vec.push_back(MyClass(2, "two"));
    vec.push_back(MyClass(8, "eight"));

    // sort by i(), ascending
    std::sort(vec.begin(), vec.end(), make_method_comparer(&MyClass::i));
    // sort by s(), ascending
    std::sort(vec.begin(), vec.end(), make_method_comparer(&MyClass::s));
    // sort by s(), descending
    std::sort(vec.begin(), vec.end(), make_method_comparer2<std::greater>(&MyClass::s));
}
Run Code Online (Sandbox Code Playgroud)


Ste*_*non 5

这是我的答案版本,只需使用 lambda 函数即可!它有效,它使用的代码更少,而且在我看来它很优雅!

#include <algorithm>
#include <vector>
#include <string>

struct MyClass
{
    int i;
    std::string s;

    MyClass(int i_, std::string const& s_) : i(i_), s(s_) { }
};

int main()
{
    std::vector<MyClass> vec;
    vec.push_back(MyClass(2, "two"));
    vec.push_back(MyClass(8, "eight"));

    // sort by i, ascending
    std::sort(vec.begin(), vec.end(), [](MyClass a, MyClass b){ return a.i < b.i; });
    // sort by s, ascending
    std::sort(vec.begin(), vec.end(), [](MyClass a, MyClass b){ return a.s < b.s; });
    // sort by s, descending
    std::sort(vec.begin(), vec.end(), [](MyClass a, MyClass b){ return a.s > b.s; });
}
Run Code Online (Sandbox Code Playgroud)