我正在为学校做一个项目,需要对一些数据进行排序。我已经获得了一个对象向量,我必须根据它们的一个属性对对象(就地或使用索引)进行排序。有几个不同的对象和几个不同的属性可以按其排序。这样做的最佳方式是什么?
答案 0 :(得分:17)
使用std::sort
和仿函数。 e.g:
struct SortByX
{
bool operator() const (MyClass const & L, MyClass const & R) { return L.x < R.x; }
};
std::sort(vec.begin(), vec.end(), SortByX());
如果L小于R,那么仿函数的operator()应该返回true,用于你想要的排序顺序。
答案 1 :(得分: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);
}
用法如下:
#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));
}
这适用于具有公共数据成员的任何类型,如果您需要以多种不同的方式对类进行排序,将会节省大量的输入。
以下是适用于公共成员函数而非公共数据成员的变体:
#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);
}
使用方式如下:
#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));
}
答案 2 :(得分:3)
这是我的答案版本,只需使用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; });
}
答案 3 :(得分:2)
sort(v.begin(), v.end(), [](const Car* lhs, const Car* rhs) {
return lhs->getPassengers() < rhs->getPassengers();
});
答案 4 :(得分:1)
编辑:替换为lambda_compare,因为我是受虐狂:
您也可以创建一个帮助程序,让您通过lambda表达式指定要使用的值:
template <class F> class lambda_compare
{
public:
lambda_compare(F f_): f(f_) { }
template <class T> bool operator()(const T &lhs, const T &rhs) const
{ return f(lhs)<f(rhs); }
private:
F f;
};
template <class F> lambda_compare<F> make_lambda_compare(F f)
{ return f; }
...
std::sort(vec.begin(), vec.end(), make_lambda_compare([](const foo &value) { return value.member; }));