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
.
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
.
Antworten:
Ü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 definiert myclass
. Alternativ können Sie definieren myclass::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;
}
};
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
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 definieren boost::lambda
. Verwenden Sie boost::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));
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;
}