Vektor aus Objekten einer Klasse nach einer Eigenschaft der Objekte sortieren



  • Hallo

    Ich habe einen Vektor aus verschiedenen Elementen einer Klasse. Ich möchte diesen Vektor gerne nach einer Eigenschaft der Klasse sortieren (z.B. für die Klasse Auto nach den PS). Wie muss eine solche Sortierfunktion in C++ aussehen?

    Für einen Vektor aus Arrays funktioniert ja die sort()Methode ganz gut - aber bei einem Vektor aus Objekten kann das ja nicht funktionieren, da Objekte nicht miteinander verglichen werden können (oder doch?).

    Beispiel-Vektor:

    class Auto  // nur grobe Darstellung ohne Methoden 
    { int PS;
      int km;
      int Türen;
    }
    
    Auto A; // mit PS(88); km (100´000); Türen (5)
    Auto B; // mit PS(55); km (120´000); Türen (5)
    Auto C; // mit PS(112); km (10´000); Türen (3)
    
    vector<Auto> Fuhrpark;
    Fuhrpark.push_back(A);
    Fuhrpark.push_back(B);
    Fuhrpark.push_back(C);
    

    Wie kann der Vektor sortiert werden, so dass z.B. an erster Stelle das Auto mit der kleinsten PS-Zahl steht?
    Ich programmiere erst 4 Wochen und stehe völlig auf dem Schlauch.

    Danke schonmal im voraus!



  • xxLKMxx schrieb:

    Hallo

    Ich habe einen Vektor aus verschiedenen Elementen einer Klasse. Ich möchte diesen Vektor gerne nach einer Eigenschaft der Klasse sortieren (z.B. für die Klasse Auto nach den PS). Wie muss eine solche Sortierfunktion in C++ aussehen?

    Für einen Vektor aus Arrays funktioniert ja die sort()Methode ganz gut - aber bei einem Vektor aus Objekten kann das ja nicht funktionieren, da Objekte nicht miteinander verglichen werden können (oder doch?).

    Wie kann der Vektor sortiert werden, so dass z.B. an erster Stelle das Auto mit der kleinsten PS-Zahl steht?
    Ich programmiere erst 4 Wochen und stehe völlig auf dem Schlauch.

    Danke schonmal im voraus!

    geht mit sort().

    schau dir das mal an:

    // sort algorithm example
    #include <iostream>     // std::cout
    #include <algorithm>    // std::sort
    #include <vector>       // std::vector
    
    bool myfunction (int i,int j) { return (i<j); }
    
    struct myclass {
      bool operator() (int i,int j) { return (i<j);}
    } myobject;
    
    int main () {
      int myints[] = {32,71,12,45,26,80,53,33};
      std::vector<int> myvector (myints, myints+8);               // 32 71 12 45 26 80 53 33
    
      // using default comparison (operator <):
      std::sort (myvector.begin(), myvector.begin()+4);           //(12 32 45 71)26 80 53 33
    
      // using function as comp
      std::sort (myvector.begin()+4, myvector.end(), myfunction); // 12 32 45 71(26 33 53 80)
    
      // using object as comp
      std::sort (myvector.begin(), myvector.end(), myobject);     //(12 26 32 33 45 53 71 80)
    
      // print out content:
      std::cout << "myvector contains:";
      for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
        std::cout << ' ' << *it;
      std::cout << '\n';
    
      return 0;
    }
    

    (habs jetzt nicht getestet aber sollte funktionieren 🙄 )

    Example - Quelle:
    http://www.cplusplus.com/reference/algorithm/sort/

    lg



  • Klappt leider nicht 😞

    Ich danke aber trotzdem erstmal für die schnelle Antwort. Ich habe mal meinen Quellcode mitgeschickt und glaube es liegt daran, dass im von dir gezeigten Verfahren ein Vektor mit Integer-Werten sortiert wird.

    Es könnte natürlich sein, dass ich die Funktion "myFunktion" oder Struct myclass falsch implementiert habe (als Referenz) aber auch beim auskommentieren dieser Teile gibt es schon ne Fehlermeldung. Wenn ich alleine die Zeile

    sort (Fuhrpark.begin(), Fuhrpark.begin()+2);
    

    implementiere kommt die Fehlermeldung: no match for "Operator <" (Operand types are "Auto" and "Auto")

    An dieser Stelle nutze ich "myfunction" und "myclass" ja noch nicht. Die Zeile müsste ja alleine also funktionieren. Ich vermute, dass liegt daran, dass ein Objekt nicht mit einem anderen Objekt verglichen werden kann (siehe Fehlermeldung) - wie kann ich definieren, dass PS die Eigenschaft ist, anhand der verglichen werden soll?? Das müsste ich doch mindestens machen, oder??

    class Auto  // nur grobe Darstellung ohne Methoden
    { public:
      int ps = 0;
      int km = 0;
      int tueren = 0;
    };
    
    bool myfunction(Auto& l, Auto& r) {return (l.ps < r.ps);}
    
    struct myclass {
      bool operator() (Auto& ll, Auto& rr) {return (ll.ps < rr.ps);}
    } myobject;
    
    int main()
    {
        Auto A; // mit PS(88); km (100´000); Türen (5)
        Auto B; // mit PS(55); km (120´000); Türen (5)
        Auto C; // mit PS(112); km (10´000); Türen (3)
        Auto D; // mit PS(100); km (25´000); Türen (4)
    
        A.ps = 88 ; A.km = 100000 ; A.tueren = 5;
        B.ps = 55 ; B.km = 120000 ; B.tueren = 5;
        C.ps = 112 ; C.km = 10000 ; C.tueren = 3;
        D.ps = 100 ; C.km = 25000 ; C.tueren = 4;
    
        vector<Auto> Fuhrpark;
        Fuhrpark.push_back(A);
        Fuhrpark.push_back(B);
        Fuhrpark.push_back(C);
        Fuhrpark.push_back(D);
    
    // Versuch der Implementierung der Sortierfunktion
    
        sort (Fuhrpark.begin(), Fuhrpark.begin()+2);
    
        sort (Fuhrpark.begin()+2, Fuhrpark.end(), myfunction);
    
        sort (Fuhrpark.begin(), Fuhrpark.end(), myobject);
    

    Hat jemand ne Idee, was ich falsch mache?



  • xxLKMxx schrieb:

    sort (Fuhrpark.begin(), Fuhrpark.begin()+2);
    

    implementiere kommt die Fehlermeldung: no match for "Operator <" (Operand types are "Auto" and "Auto")

    Die Meldung ist doch erstaunlich klar: Es gibt kein < für Auto und wenn sort nicht weiß, welches Auto "kleiner" ist, kann es nicht sortieren.



  • Hallo Manni,

    das habe ich ja auch geschrieben. Kann aufgrund meiner geringen Programmierkenntnisse leider nicht so selbstbewusst auftreten und frage mich immer noch, vielleicht hab ich auch ein anderen Fehler gemacht.

    Jetzt bleibt jedoch die Frage, wie sage ich dem Compiler, das er Autos anhand des PS-Wertes im Vektor sortieren soll?



  • Es genügt eine Zeile mit sort:

    sort (Fuhrpark.begin(), Fuhrpark.end(), myfunction);
    

    Man könnte jetzt natürlich auch einen Namen verwenden, der besser zum Inhalt der Funktion passt.

    Generell: ohne ein anständiges Buch (Suchfunktion, Threads für Anfänger!) oder einen anständigen Kurs wird das schwierig. Offensichtlich war die verlinkte Referenz ja schon zu knapp für dich und selbst eine so lange Erklärung werde ich hier nicht schreiben.



  • xxLKMxx schrieb:

    An dieser Stelle nutze ich "myfunction" und "myclass" ja noch nicht. Die Zeile müsste ja alleine also funktionieren. Ich vermute, dass liegt daran, dass ein Objekt nicht mit einem anderen Objekt verglichen werden kann (siehe Fehlermeldung) ...

    genau so ist es. Man muss dem sort noch mitteilen, wie er vergleichen soll. Ohne 3.Parameter würde sort den <-operator nutzen, den die Klasse Auto aber nicht besitzt. Eine andere Möglichkeit besteht darin, einen Funktor als Lambda-Ausdruck anzugeben. Das geht so:

    #include <algorithm>    // sort
    #include <vector>
    #include <iostream>
    
    class Auto
    {
    public:
        Auto( int ps, int Km, int anzTueren )
            : PS( ps ), km( Km ), Tueren( anzTueren )
        {}
    
        int PS;
        int km;
        int Tueren;
    };
    
    std::ostream& operator<<( std::ostream& out, const Auto& a )
    {
        return out << "Auto " << a.PS << "PS " << a.km << "km " << a.Tueren << "Türen"; 
    }
    
    int main()
    {
        using namespace std;
        vector< Auto > Fuhrpark;
        Fuhrpark.push_back( Auto( 88, 100000, 5 ) );
        Fuhrpark.push_back( Auto( 55, 120000, 5 ) );
        Fuhrpark.push_back( Auto( 112, 10000, 3 ) );
    
        cout << ".. nach PS:" << endl;
        sort( begin(Fuhrpark), end(Fuhrpark), []( const Auto& a, const Auto& b ) { return a.PS < b.PS; } ); // sortiere nach PS aufsteigend
        for( auto pkw: Fuhrpark )
            cout << pkw << endl;
    
        cout << "\n.. nach Kilometer-Leistung:" << endl;
        sort( begin(Fuhrpark), end(Fuhrpark), []( const Auto& a, const Auto& b ) { return a.km < b.km; } ); // sortiere nach km aufsteigend
        for( auto pkw: Fuhrpark )
            cout << pkw << endl;
    
        return 0;
    }
    

Anmelden zum Antworten