Ordenar un vector de objetos por una propiedad del objeto

Estoy trabajando en un proyecto para la escuela y necesito ordenar algunos datos. Me han dado un vector de objetos y tengo que ordenar los objetos (en su lugar o usando un índice) en función de una de sus propiedades. Hay varios objetos diferentes y varias propiedades diferentes por las que podría clasificarse. ¿Cuál es la mejor manera de hacer esto?

Hay varios objetos diferentes y varias propiedades diferentes por las que podría clasificarse.

Si bien la solución que Erik publicó es correcta, esta afirmación me lleva a pensar que no es práctico en el mejor de los casos si de hecho está planeando ordenar por múltiples miembros de datos públicos de múltiples clases en múltiples formas en el mismo progtwig, ya que cada método de clasificación requerirá su propio tipo de functor.

Recomiendo la siguiente abstracción:

#include  template class C = std::less> struct member_comparer : std::binary_function { explicit member_comparer(MT::*p) : p_(p) { } bool operator ()(T const& lhs, T const& rhs) const { return C()(lhs.*p_, rhs.*p_); } private: MT::*p_; }; template member_comparer make_member_comparer(MT::*p) { return member_comparer(p); } template class C, typename T, typename M> member_comparer make_member_comparer2(MT::*p) { return member_comparer(p); } 

El uso se vería así:

 #include  #include  #include  struct MyClass { int i; std::string s; MyClass(int i_, std::string const& s_) : i(i_), s(s_) { } }; int main() { std::vector 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(&MyClass::s)); } 

Esto funcionará para cualquier tipo con miembros de datos públicos, y guardará una gran cantidad de tipeo si necesita ordenar sus clases más de un par de maneras diferentes.

Aquí hay una variación que funciona con funciones de miembros públicos en lugar de miembros de datos públicos:

 #include  template class C = std::less> struct method_comparer : std::binary_function { explicit method_comparer(M (T::*p)() const) : p_(p) { } bool operator ()(T const& lhs, T const& rhs) const { return C()((lhs.*p_)(), (rhs.*p_)()); } private: M (T::*p_)() const; }; template method_comparer make_method_comparer(M (T::*p)() const) { return method_comparer(p); } template class C, typename T, typename M> method_comparer make_method_comparer2(M (T::*p)() const) { return method_comparer(p); } 

Con el uso como:

 #include  #include  #include  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 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(&MyClass::s)); } 

Use std::sort y un functor. p.ej:

 struct SortByX { bool operator() const (MyClass const & L, MyClass const & R) { return Lx < Rx; } }; std::sort(vec.begin(), vec.end(), SortByX()); 

El operador del operador () debe devolver verdadero si L es menor que R para el orden de clasificación que desee.

Aquí está mi versión de la respuesta, ¡simplemente use una función lambda! Funciona, usa mucho menos código, ¡y en mi opinión es elegante!

 #include  #include  #include  struct MyClass { int i; std::string s; MyClass(int i_, std::string const& s_) : i(i_), s(s_) { } }; int main() { std::vector 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 ai < bi; }); // sort by s, ascending std::sort(vec.begin(), vec.end(), [](MyClass a, MyClass b){ return as < bs; }); // sort by s, descending std::sort(vec.begin(), vec.end(), [](MyClass a, MyClass b){ return as > bs; }); } 

EDITAR: reemplazando con lambda_compare, porque soy masoquista:

También puedes simplemente crear un helper que te permita especificar qué valor usar a través de una expresión lambda:

 template  class lambda_compare { public: lambda_compare(F f_): f(f_) { } template  bool operator()(const T &lhs, const T &rhs) const { return f(lhs) lambda_compare make_lambda_compare(F f) { return f; } ... std::sort(vec.begin(), vec.end(), make_lambda_compare([](const foo &value) { return value.member; }));