Ich würde gerne eine sortieren vector
vector<myClass> object;
Wo myclass
enthält viele int
Variablen. Wie kann ich meine sortieren vector
auf eine bestimmte Datenvariable myClass
.
Überladen Sie weniger als der Operator und sortieren Sie dann. Dies ist ein Beispiel, das ich aus dem Internet gefunden habe ...
class MyData
{
public:
int m_iData;
string m_strSomeOtherData;
bool operator<(const MyData &rhs) const { return m_iData < rhs.m_iData; }
};
std::sort(myvector.begin(), myvector.end());
Quelle: hier
std::sort(object.begin(), object.end(), pred());
Dabei
pred()
ist ein Funktionsobjekt, das die Reihenfolge für Objekte von definiertmyclass
. Alternativ können Sie definierenmyclass::operator<
.Zum Beispiel können Sie ein Lambda übergeben:
std::sort(object.begin(), object.end(), [] (myclass const& a, myclass const& b) { return a.v < b.v; });
Oder wenn Sie mit C ++ 03 nicht weiterkommen, ist der Funktionsobjektansatz (
v
das Element, nach dem Sie sortieren möchten):struct pred { bool operator()(myclass const & a, myclass const & b) const { return a.v < b.v; } };
quelle
Mit einem Zeiger auf ein Mitglied können Sie einen einzelnen Komparator schreiben, der mit jedem Datenelement Ihrer Klasse arbeiten kann:
#include <algorithm> #include <vector> #include <string> #include <iostream> template <typename T, typename U> struct CompareByMember { // This is a pointer-to-member, it represents a member of class T // The data member has type U U T::*field; CompareByMember(U T::*f) : field(f) {} bool operator()(const T &lhs, const T &rhs) { return lhs.*field < rhs.*field; } }; struct Test { int a; int b; std::string c; Test(int a, int b, std::string c) : a(a), b(b), c(c) {} }; // for convenience, this just lets us print out a Test object std::ostream &operator<<(std::ostream &o, const Test &t) { return o << t.c; } int main() { std::vector<Test> vec; vec.push_back(Test(1, 10, "y")); vec.push_back(Test(2, 9, "x")); // sort on the string field std::sort(vec.begin(), vec.end(), CompareByMember<Test,std::string>(&Test::c)); std::cout << "sorted by string field, c: "; std::cout << vec[0] << " " << vec[1] << "\n"; // sort on the first integer field std::sort(vec.begin(), vec.end(), CompareByMember<Test,int>(&Test::a)); std::cout << "sorted by integer field, a: "; std::cout << vec[0] << " " << vec[1] << "\n"; // sort on the second integer field std::sort(vec.begin(), vec.end(), CompareByMember<Test,int>(&Test::b)); std::cout << "sorted by integer field, b: "; std::cout << vec[0] << " " << vec[1] << "\n"; }
Ausgabe:
sorted by string field, c: x y sorted by integer field, a: y x sorted by integer field, b: x y
quelle
template <typename T, typename U, U (T::*F)> struct CompareByMember2 { bool operator()(const T &lhs, const T & rhs) { return lhs.*F < rhs.*F; }};
. Ob dies möglich ist, hängt davon ab, ob der Anrufer eine Variable verwendet, nach der das Mitglied sortieren kann, oder ob verschiedene Anrufer unterschiedliche spezifische Mitglieder angeben.Wie in anderen Antworten erläutert, müssen Sie eine Vergleichsfunktion bereitstellen. Wenn Sie die Definition dieser Funktion in der Nähe des
sort
Aufrufs halten möchten (z. B. wenn dies nur für diese Art sinnvoll ist), können Sie sie genau dort mit definierenboost::lambda
. Verwenden Sieboost::lambda::bind
diese Option , um die Member-Funktion aufzurufen.So z. B. nach Mitgliedsvariable oder Funktion sortieren
data1
:#include <algorithm> #include <vector> #include <boost/lambda/bind.hpp> #include <boost/lambda/lambda.hpp> using boost::lambda::bind; using boost::lambda::_1; using boost::lambda::_2; std::vector<myclass> object(10000); std::sort(object.begin(), object.end(), bind(&myclass::data1, _1) < bind(&myclass::data1, _2));
quelle
Dies ist mein Ansatz, um dies allgemein zu lösen. Es erweitert die Antwort von Steve Jessop, indem die Anforderung zum expliziten Festlegen von Vorlagenargumenten entfernt und die Option hinzugefügt wird, auch Funktionen und Zeiger auf Methoden (Getter) zu verwenden.
#include <vector> #include <iostream> #include <algorithm> #include <string> #include <functional> using namespace std; template <typename T, typename U> struct CompareByGetter { U (T::*getter)() const; CompareByGetter(U (T::*getter)() const) : getter(getter) {}; bool operator()(const T &lhs, const T &rhs) { (lhs.*getter)() < (rhs.*getter)(); } }; template <typename T, typename U> CompareByGetter<T,U> by(U (T::*getter)() const) { return CompareByGetter<T,U>(getter); } //// sort_by template <typename T, typename U> struct CompareByMember { U T::*field; CompareByMember(U T::*f) : field(f) {} bool operator()(const T &lhs, const T &rhs) { return lhs.*field < rhs.*field; } }; template <typename T, typename U> CompareByMember<T,U> by(U T::*f) { return CompareByMember<T,U>(f); } template <typename T, typename U> struct CompareByFunction { function<U(T)> f; CompareByFunction(function<U(T)> f) : f(f) {} bool operator()(const T& a, const T& b) const { return f(a) < f(b); } }; template <typename T, typename U> CompareByFunction<T,U> by(function<U(T)> f) { CompareByFunction<T,U> cmp{f}; return cmp; } struct mystruct { double x,y,z; string name; double length() const { return sqrt( x*x + y*y + z*z ); } }; ostream& operator<< (ostream& os, const mystruct& ms) { return os << "{ " << ms.x << ", " << ms.y << ", " << ms.z << ", " << ms.name << " len: " << ms.length() << "}"; } template <class T> ostream& operator<< (ostream& os, std::vector<T> v) { os << "["; for (auto it = begin(v); it != end(v); ++it) { if ( it != begin(v) ) { os << " "; } os << *it; } os << "]"; return os; } void sorting() { vector<mystruct> vec1 = { {1,1,0,"a"}, {0,1,2,"b"}, {-1,-5,0,"c"}, {0,0,0,"d"} }; function<string(const mystruct&)> f = [](const mystruct& v){return v.name;}; cout << "unsorted " << vec1 << endl; sort(begin(vec1), end(vec1), by(&mystruct::x) ); cout << "sort_by x " << vec1 << endl; sort(begin(vec1), end(vec1), by(&mystruct::length)); cout << "sort_by len " << vec1 << endl; sort(begin(vec1), end(vec1), by(f) ); cout << "sort_by name " << vec1 << endl; }
quelle