Vector: min_element eines Vector mit Objekten



  • Klotz schrieb:

    @Manni66:
    Ich dachte, "Auftragnehmerkopie" ist die Instanz des Vector...

    Ja, ist es auch.

    Klotz schrieb:

    Ausgabe per Iterator:

    std::vector<AN> Auftragnehmerkopie;
    std::vector<AN>::const_iterator its;
    //Werte füllen
    for (its=Auftragnehmerkopie.begin();its!=Auftragnehmerkopie.end();its++)
    { cout<<(*its)<<endl;
    }
    

    Im Prinzip ja, aber das gibt nicht nur die DKNummer aus.
    begin() ist also ein Member des Vectors und leifert einen Iterator!

    Klotz schrieb:

    O.K. Ich sehe glaube ich den ersten Fehler. Ich kann distance() nicht direkt mit einer (int) abrufen, da es einen Zeiger zurück gibt?

    std::distannce wird mit Itaratoren aufgerufen.
    std::min_element wird auch mit Iteratoren aufgerufen und liefert einen Iterator zurück. Da du nicht zwei AN-Objekte vergleichen willst sondern jeweils nur eine Element dieser Objekte brauchst du eine Vergleichsfunktion.

    Das Ganze baust du am Besten erst mal Schritt für Schritt auf, beginnend mit min_element.



  • Was du brauchst ist die Funktion mit 3 Parametern: min_element

    template< class ForwardIt, class Compare >
    ForwardIt min_element( ForwardIt first, ForwardIt last, Compare comp );



  • temi schrieb:

    Auftragnehmerkopie ist schon ein Vector...

    Hoppla, das habe ich hart ueberlesen. Mein Fehler!



  • Hi,

    bevor ich damit starte, Eure Weisungen durchzugehen, habe ich ein Problem. Der compiler meldet mir ständig, dass die Variable DKNummer kein Bestandteil des Vector ist.

    Generell habe ich die Klasse über den STandartkonstruktor erzeugt und dann einen Vector gebildet. Ich habe aber den Eindruck, dass da irgendwas noch nicht richtig ist. Generell ist das noch so ein Schwachpunkt bei mir.

    Ablauf ist bisher:

    AN AN_Element;
    
    vector<AN> Auftragnehmer;
    // beide global
    
    // dann in der WM_PAINT
     vector<AN> Auftragnehmerkopie(Auftragnehmer);
    
    //folgend die AN.hpp
    #ifndef AN_HPP_INCLUDED
    #define AN_HPP_INCLUDED
    
    #include <iostream>
    #include <string>
    #include <vector>
    #include <windows.h>
    #include <commctrl.h>
    #include "Nachtrag.hpp"
    #include "Rechnung.hpp"
    #include "KKE.hpp"
    
    using namespace std;
    
    class AN:public KKE
    {
    public:
        int KKENummer;
        int KABNummer;
        int DKNummer;
        int Auftragsnummer;
        AN();
        ~AN();
    // es folgen einige public Funktionen und private Dateien
    }
    


  • Klotz schrieb:

    bevor ich damit starte, Eure Weisungen durchzugehen, habe ich ein Problem. Der compiler meldet mir ständig, dass die Variable DKNummer kein Bestandteil des Vector ist.

    Und damit liegt er natürlich vollkommen richtig.



  • Klotz schrieb:

    Hi,

    bevor ich damit starte, Eure Weisungen durchzugehen, habe ich ein Problem. Der compiler meldet mir ständig, dass die Variable DKNummer kein Bestandteil des Vector ist.

    DKNummer ist ein Bestandteil von AN und in deinem Vector speicherst du Objekte vom Typ AN.

    Und bevor das Nächste was du probierst auch nicht funktioniert: AN ist auch kein Bestandteil des Vectors. Lies dir einfach mal durch, wie du auf die im Vector gespeicherten Daten zugreifen kannst.

    Edit: z.B. hier: http://www.cplusplus.com/reference/vector/vector/ unter Element access



  • Klotz schrieb:

    Der compiler meldet mir ständig, dass die Variable DKNummer kein Bestandteil des Vector ist.

    Du scheinst dir das so vorzustellen, dass der vector<AN> einen "Untervektor" vector<int> DKNummer enthält, der wiederum die DKNummer-Member deiner ANs enthält.

    Das ist aber nicht der Fall.



  • Hallo,

    habe jetzt endlich Zeit, weiter zu machen. Leider weiß ich nicht, wie ich die Iteratorfunktion schreiben soll.

    for ( vector<AN>::iterator it = Auftragnehmerkopie.begin(); it !=Auftragnehmerkopie.end();)
               {
    
                   DKmin=*min_element(it->DKNummer.begin(),it->DKNummer.end());
    
                 /*  if
                   {
    
                   }
    */
                 else
               {
                   ++it;
               }
               }
    

    Dachte, dass es so jetzt stimmen müsste, aber der compiler meldet:
    "error: request for member 'begin' in 'it.gnu_cxx:_normal_iterator<...which is of non-class type int"

    Das sagt mir nicht viel. Ist jetzt DKmin falsch (int), oder der it->... code- Teil?



  • Ach Mist, ich komme nicht weiter 😕



  • Hallo,

    DKNummer ist ein 'int' und hat keine begin oder end-Funktion!
    Nur ein vector stellt diese bereit.

    Wie ich schon schrieb, benötigst du die Funktion mit der Vergleichsfunktion als Parameter:

    min_element(Auftragnehmerkopie.begin(), Auftragnehmerkopie.end(), cmp_by_DKNummer);
    

    Und nun noch die Vergleichsfunktion 'cmp_by_DKNummer' entsprechend implementieren...



  • In der Doku findest du ein Beispiel:

    http://www.cplusplus.com/reference/algorithm/min_element/



  • Hallo,

    Mensch. Danke schon mal. Ich glaube, ich habe es jetzt. Ich schreibe mal die Funktion fertig und poste dann das Ergebnis. Ich stand echt auf dem Schlauch. Vielen Dank.

    Mir war nicht klar, dass min_element drei Parameter braucht.

    Grüße,
    Chris



  • Es gibt auch die Variante mit nur zwei Parametern, aber dann vergleicht diese Funktion anhand des Operator < (der aber für deine Klasse AN bisher wohl nicht definiert ist) - aber das steht auch alles in den geposteten Links zur Doku. 😉



  • Hallo,

    ich poste mal einen Zwischenstand und würde mich über Rückmeldung freuen, weil ich eine Fehlermeldung bekomme, die ich noch nicht zuordnen kann.

    In WinMain:

    if (!Auftragnehmerkopie.empty())
                {
                for ( vector<AN>::iterator it = Auftragnehmerkopie.begin(); it !=Auftragnehmerkopie.end();)
                {
                if (it != Auftragnehmerkopie.end()&&ANGroesse>1)
                {
                DKpos=std::min_element(it->DKNummer, it->DKNummer+ANGroesse,PruefeVektorausgabe); //*
    
                DKmin=Auftragnehmerkopie[DKpos].DKNummer;
    
    bool PruefeVektorausgabe(const AN& x, const AN& y)
    {
        return x.DKNummer<y.DKNummer;
    }
    

    Der compiler meldet mir für die Zeile // *
    "invalid type argument of unary '*' (have 'int')

    Ich ahne, dass das was mit dem dritten Parameter von min_element zu tun hat.

    Generell habe ich versucht, über zwei Instanzen von <AN> die DKNummer zu vergleichen. Das scheint aber nicht zu funktionieren. Vielleicht, weil da ein Zeiger in die Funktion mitgegeben wird und kein (int)? Und die Funktion ist eine (bool)? Ist das so überhaupt richtig? Müsste nicht eine (int) erfolgen?

    Kann mir das jemand erklären? Das wäre sehr nett.



  • Th69 schrieb:

    min_element(Auftragnehmerkopie.begin(), Auftragnehmerkopie.end(), cmp_by_DKNummer);
    

    Th69 hat doch schon geschrieben, wie dein Code aussehen müsste. Hast du dir die Doku zu min_element durchgelesen? Wo steht da, dass man das mit "int" aufrufen kann? it->DKNummer ist ein int

    Die ganze Schleife kannst du dir schenken, das erledigt min_element für dich, wenn du die passenden iteratoren übergibst.



  • Wie bereits gesagt: min_element nimmt Iteratoren und liefert auch einen zurück.

    Iteratoren gehören zum grundlegenden Konzept der STL. Schau dir das noch einmal genauer an.



  • Hallo.

    Ich bin jetzt zumindest in der Lage, EIN Mindestelement zu filtern und dessen Position und Wert zu speichern.

    if (!Auftragnehmerkopie.empty())
                {
    
                std::vector<AN>::iterator resultDK=std::min_element(Auftragnehmerkopie.begin(), Auftragnehmerkopie.end(), PruefeVektorausgabe);
                DKpos=std::distance(Auftragnehmerkopie.begin(),resultDK);
                DKmin=Auftragnehmerkopie[DKpos].DKNummer;
    
    //...
    bool PruefeVektorausgabe(const AN& x, const AN& y)
    {
    
        return x.DKNummer<y.DKNummer;
    }
    }
    

    Nun ergibt sich für mich folgende Frage. Da es mehrere Vector Elemente gibt, die den selben DKNummer Wert haben, möchte ich unter diesen noch drei weitere Werte filtern, um das ELement zu erhalten, das überall den niedrigsten Wert hat, dieses ausgeben und dann aus dem Vector löschen.

    Ich möchte in diesem Zusammenhang wissen, ob ich DKmin als Parameter in der std::min_element Abfrage als Parameter mitgeben kann, so dass das nächste Mindestelement nur unter den Elementen gesucht wird, die DKNummer==DKmin erfüllen; in etwa:

    resultKAB=std::min_element(Auftragnehmerkopie.begin()&&DKNummer==DKmin, Auftragnehmerkopie.end(), PruefeKABausgabe);

    Wie kann ich so etwas schaffen? Leider geben da meine Bücher keine Antwort und google hilft mir auch nicht viel weiter. Geht das überhaupt?



  • Es gibt kaum Sachen, die nicht gehen...

    bool PruefeVektorausgabe(const AN& x, const AN& y){
       if(x.DKNummer == y.DKNummer){
          ...
       }
        return x.DKNummer<y.DKNummer;
    }
    


  • Folgende beiden Wege finde ich für den Vergleich anhand mehrerer Bedingungen am einfachsten:

    Variante 1, make_tuple:

    bool PruefeVektorausgabe(const AN& x, const AN& y){
       return make_tuple(x.DKNummer, x.andere_variable, x.noch_was_anderes)
            < make_tuple(y.DKNummer, y.andere_variable, y.noch_was_anderes);
    }
    

    Tuples sortieren sich von links nach rechts, d.h. das vergleicht also erst DKNummer , dann bei Gleichheit andere_variable , und wenn dann immer noch beides gleich ist, wird noch_was_anderes verglichen.

    Variante 2:

    bool PruefeVektorausgabe(const AN& x, const AN& y){
        if (x.DKNummer < y.DKNummer) return true;
        if (x.DKNummer != y.DKNummer) return false;
    
        if (x.andere_variable < y.andere_variable) return true;
        if (x.andere_variable != y.andere_variable) return false;
    
        return x.noch_was_anderes < y.noch_was_anderes;
    }
    

    Die Variante 2 finde ich deutlich besser als Schlangenmenschs Weg mit if und dann einem Block bei Gleichheit. Der führt nämlich zu Verschachtelungen und ist schwerer zu lesen, insbesondere wenn man viele Vergleichsvariablen hat.



  • @wob: tatsächlich finde ich deine Ansätze auch besser als meinen. Meiner war vor allem als kurzer Denkanstoß an den TE gedacht, dass man in der Sortierfunktion mehr machen kann als nur einen Vergleich.


Anmelden zum Antworten