Vector sortieren
-
Hallo .
Wie die Überschrift schon ausdrückt habe ich einen Vector, den ich sortieren möchte. Ich habe einen eigenen Datentyp geschrieben den der Vector aufnimmt. Daher geht der Standart sort Befehl nicht. Ich muss ihn also Überschreiben. Das ist mir klar. ICh würde diese Funktion gerne in eine Klasse ansiedeln. Geht das ?
Und meine 2 Frage ich würde der Sortier funktion einen Parameter übergegebn, der angibt wonach sortiert werden soll.Kann mir dabei jemand auf die Sprünge helfen?
-
1. Schreib dir einen Functor, der den Vergleich übernimmt (Anleitungen gibts dazu haufenweise im Netz)
2. Benutz std::sort mit einer Instanz des Functors als Comparator.
-
Eigentlich ist da std::sort genauso verwendbar.
http://www.cplusplus.com/reference/algorithm/sort/
Du schreibst dir eine Klasse "Comparator", dort überlädst du operator():class Comparator { public: bool operator()(const MyType& left, const MyType& right); };
so dass wie in der Doku angegeben gilt:
returns true if the first argument goes before the second argument in the specific strict weak ordering it defines, and false otherwise.
Da comparator eine Klasse ist kannst du beliebig Member hinzufügen, so dass du z.B. ne sortOrder angeben kannst, oder ein bestimmtes Sortierkriterium (sortiere nach name, nach Farbe, oder erst nach Name dann nach Farbe, usw.)
Schau dir auch das Beispiel an, welches auf der Seite angegeben ist (dich interessiert das mit dem myclass).
-
Vielen Dank genau soetwas habe ich gesucht
-
Functor ... eine Klasse "Comparator"
Es reicht auch eine einfache Funktion.
-
knivil schrieb:
Functor ... eine Klasse "Comparator"
Es reicht auch eine einfache Funktion.
Ja klar, aber
Fischkopf2009 schrieb:
Und meine 2 Frage ich würde der Sortier funktion einen Parameter übergegebn, der angibt wonach sortiert werden soll.
Und das geht nunmal mit einer freien Funktion schlecht (außer man fängt mit globalen Sortier-Indikatoren an...).
-
l'abra d'or schrieb:
Und das geht nunmal mit einer freien Funktion schlecht (außer man fängt mit globalen Sortier-Indikatoren an...).
Man benutzt dann z.B. boost.bind
-
Der Parameter fuer die Sortierroutine ist die Vergleichsfunktion. Mehr braucht man fuer gewoehnlich nicht. Hier ein Tutorial, das ich dazu mal geschrieben habe: Sortieren in C++ für Fortgeschrittene. Dort sind alle Moeglichkeiten an Hand von sinnvollen Beispielen beschrieben (ohne boost).
-
evilissimo schrieb:
l'abra d'or schrieb:
Und das geht nunmal mit einer freien Funktion schlecht (außer man fängt mit globalen Sortier-Indikatoren an...).
Man benutzt dann z.B. boost.bind
Und hat wieder ein Funktionsobjekt
Ob ich nu eine freie Funktion habe und die bei jedem Aufruf von sort und an anderen Stellen wo ich sie brauche mit einem länglichen boost::bind verziere, oder gleich ein struct mache und mit wenig mehr Tip-Aufwand das binden gleich selbst übernehme, ein großer Unterschied ist da nicht, mal abgesehen davon dass ich den Typ des Comparators kenne und z.B. bei std::maps mit angeben kann - oder weiß jemand auswendig, was der exakte Typ von boost::bind(myFunc,5) ist?
-
pumuckl schrieb:
evilissimo schrieb:
l'abra d'or schrieb:
Und das geht nunmal mit einer freien Funktion schlecht (außer man fängt mit globalen Sortier-Indikatoren an...).
Man benutzt dann z.B. boost.bind
Und hat wieder ein Funktionsobjekt
Ob ich nu eine freie Funktion habe und die bei jedem Aufruf von sort und an anderen Stellen wo ich sie brauche mit einem länglichen boost::bind verziere, oder gleich ein struct mache und mit wenig mehr Tip-Aufwand das binden gleich selbst übernehme, ein großer Unterschied ist da nicht, mal abgesehen davon dass ich den Typ des Comparators kenne und z.B. bei std::maps mit angeben kann - oder weiß jemand auswendig, was der exakte Typ von boost::bind(myFunc,5) ist?Der typ der von boost bind zurück gegeben wird tut gar nichts zur sache. std::sort ist das doch egal was für ein typ das ist, dafür ist es ein template.
Wichtig zuwissen ist das man das zum beispiel boost::function zuweisen kann. Je nach signatur.Deine Argumentation das man dann ein funktionsobjekt hat macht jetzt nicht wirklich Sinn. Und das man dann mit etwas mehr aufwand das selber machen kann zeigt das du schein bar keine Ahnung hast was boost::bind eigentlich tut und wie man das verwendet.
Nur mal so als beispiel:
std::sort(employees.begin(), employees.end(), boost::bind( employee_sort_func, _1, _2, sort_by_name_tag ) ); std::sort(employees.begin(), employees.end(), boost::bind( employee_sort_func, _1, _2, sort_by_age_tag ) ); std::sort(employees.begin(), employees.end(), boost::bind( employee_sort_func, _1, _2, sort_by_salary_tag ) );
Dazu brauch ich ja wohl nichts mehr sagen oder
Edit: Ach ja und wenn dir der boost::bind aufruf zu umständlich sein sollte weil du ganz ganz viele kriterien hast und du sehr viele plätze hast an denen du das aufrufst, kannst du dir das auch noch mal abkürzen:
void sort_employees( std::vector< employee > & v, employee_sort_tag tag ) { std::sort(v.begin(), V.end(), boost::bind( employee_sort_func, _1, _2, tag ) ); } sort_employees( employees, sort_by_name_tag ); sort_employees( employees, sort_by_age_tag ); sort_employees( employees, sort_by_salary_tag );
Die gegen die freie Funktion würde nichts sprechen. Natürlich kannst du dir das auch in ein funktions objekt selbst wrappen, aber dann hättest du das von anfang an gemacht.
Das mit dem boost.bind Beispiel wurde auch nur von mir genannt da l'abra d'or meinte man könne das schlecht mit freien funktionen machen.
-
evilissimo schrieb:
Nur mal so als beispiel:
std::sort(employees.begin(), employees.end(), boost::bind( employee_sort_func, _1, _2, sort_by_name_tag ) ); std::sort(employees.begin(), employees.end(), boost::bind( employee_sort_func, _1, _2, sort_by_age_tag ) ); std::sort(employees.begin(), employees.end(), boost::bind( employee_sort_func, _1, _2, sort_by_salary_tag ) );
struct EmployeeComp { EmployeeComp(Tag t) : tag(t) {} bool operator()(Employee const& lhs, Employee const& rhs); Tag tag; }; std::sort(employees.begin(), employees.end(), EmployeeComp(sort_by_name_tag) ); std::sort(employees.begin(), employees.end(), EmployeeComp(sort_by_age_tag) ); std::sort(employees.begin(), employees.end(), EmployeeComp(sort_by_salary_tag) );
Kein großer Unterschied im Aufwand, oder? Genauer gesagt 6 Zeilen, davon eine Leerzeile und zweimal nur Klammern - abzüglich dem länglichen boost::bin-rattenschwanzz bei jedem Aufruf.
[quote="evilissimo"]Der typ der von boost bind zurück gegeben wird tut gar nichts zur sache. std::sort ist das doch egal was für ein typ das ist, dafür ist es ein template. [quote] Ich hab auch nicht behauptet, dass man für sort den Typ wissen muss. Für std::map mit entsprechendem Comparator braucht mans eben schon, und den Bonus kriegt man eben wenns manuell gemacht wird.
Und das man dann mit etwas mehr aufwand das selber machen kann zeigt das du schein bar keine Ahnung hast was boost::bind eigentlich tut und wie man das verwendet.
Ich denk schon dass ich ne recht passable Ahnung hab was boost::bin macht und wie mans verwendet - ich wollte nur aufzeigen dass man je nach Situation entscheiden sollte und nicht immer pauschal auf boost::bind zurückfallen sollte nur weil mans zur Verfügung hat.
Das mit dem boost.bind Beispiel wurde auch nur von mir genannt da l'abra d'or meinte man könne das schlecht mit freien funktionen machen.
Okay, dann haben wir wohl aneinander vorbeigeschrieben und/oder -gedacht. Kleines Missverständnis am Rande
-
Würde bind nicht verwenden weil es a) scheisse zu lesen ist, b) beschissen zu erweitern ist, c) eine Drittbibliothek ist (Pest).
-
Fellhuhn schrieb:
Würde bind nicht verwenden weil es a) scheisse zu lesen ist, b) beschissen zu erweitern ist, c) eine Drittbibliothek ist (Pest).
a) Ja.
b) Kommt drauf an, kann bein Selbstgestricktem genauso der Fall sein
c) Gibts einen Grund für diesen dogmatischen Ansatz kontra eine Drittbibliothek, (vor allem wenn man sie eh ständig verwendet)?
-
Zu c) wenn man sie gar nicht verwendet gibt es keinen Grund sie wegen so etwas reinzulinken.
-
Fellhuhn schrieb:
Zu c) wenn man sie gar nicht verwendet gibt es keinen Grund sie wegen so etwas reinzulinken.
reinlinken ist da ein wenig übertrieben, denn Boost besteht grösstenteils aus Header- Only Libraries.