Vektoren vergleichen



  • Hallo zusammen,

    ich habe ein Problem beim vergleichen von zwei Vektoren.

    vektor1 = {0 1 3 21 22 23 24 25}
    vektor2 = {0 1 3 22 24 25}
    

    Diese sollen nun verglichen werden und falls ein element in beiden vorhanden ist, soll dieses in einen 3. Vektor geschrieben werden. ist das Element nicht vorhanden, soll eine 0 eingetragen werden.
    Ich mach das so:

    for(int i=0; i<vektor1.size()-1; i++){
    
    		int d1 = vektor1.at(i);
    		for(int g=0; g<vektor2.size()-1; g++){
    			
    			int d2 = vektor2.at(g);
    
    			if(d1==d2){
    				
    				vektor3.push_back(d2);
    				
    			}else if(d1!=d2){
    				vektor3.push_back(0);
    				
    			}
    
    		}
    	}
    

    Lass ich mir das jetzt ausgeben, bekomme ich nur 0. Die Ausgabe sollte ja aber "0 1 3 0 22 0 24 25" sein.
    Kann mir jemand sagen was ich falsch mache bzw. wie es richtig geht?
    Vielen Dank



  • @Luc sagte in Vektoren vergleichen:

    Lass ich mir das jetzt ausgeben, bekomme ich nur 0. Die Ausgabe sollte ja aber "0 1 3 0 22 0 24 25" sein.

    Ich sehe keine Ausgabe, nur einen unvollständigen Programmschnipsel. Ich würde ziemlich viele Nullen und ein paar Zahlen erwarten.

    Benutze eine Debugger und führe das Programm schrittweise aus. Dann solltest du ein Problem erkennen.



  • @Luc sagte in Vektoren vergleichen:

    i<vektor1.size()-1;

    Warum -1?



  • @manni66 Ja ich bekomme nur Nullen. Irgendwie ist die Bedingung bei else if falsch.
    wenn ich dir jetzt mein komplettes Programm hinklatsche gibts auch bloß wieder gemecker, das was ich geschrieben hatte reicht doch völlig aus um das Problem zu verstehen und evtl zu helfen.



  • Zum einen sind deine Bedingungen der beiden for-Schleifen nicht ganz korrekt, dein Hauptfehler ist aber, daß du schon in der innersten Schleife bei Ungleichheit eine 0 erzeugst (also evtl. schon nach dem ersten Vergleich).
    Am besten du schreibst dir eine Funktion, welches überprüft, ob eine (als Parameter übergebene) Zahl in einem vector vorkommt. Diese rufst du dann jeweils in einer Schleife für die Zahlen des ersten vector auf.



  • @Luc sagte in Vektoren vergleichen:

    Ja ich bekomme nur Nullen.

    Das glaube ich nicht.

    reicht doch völlig aus

    siehe oben.


  • Mod

    Dein Algorithmus ist falsch. Du packst auf jeden Fall viel zu viele Nullen rein. Denk mal an den Schritt i = 0: Dann ist d1 auch 0. Dann gehst du durch den zweiten Vektor durch. Beim ersten Schritt ist dieser zufällig auch 0, und du schreibst eine 0 in den Zielvektor (hier rächt sich die ungünstige Aufgabenstellung, bei der man "nicht in beiden gefunden" nicht von "Null ist in beiden" unterscheiden kann 👎 ). Dann gehst du weiter zur 1. Die ist nicht gleich 0 und du schreibst noch eine Null in den Zielvektor. Und das machst du dann ganz oft noch mal.

    Du brauchst einen ganz anderen Ansatz. Ein Teil des Ansatzes sollte auch sein, dass du die Vorsortierung der Werte ausnutzt.

    Desweiteren machst du noch Anfängerfehler bei der Iteration. for(int g=0; g<vektor2.size()-1; g++) geht nicht durch den ganzen vektor2. Du hast offenbar mal etwas davon gehört, dass Vektorindizes im Intervall [0, Länge-1] liegen, aber denk mal genauer nach, welche Werte das g annehmen kann.



  • @SeppJ Hast du mir da einen Ansatz? ich hirne seit stunden daran rum und komme auf nichts..



  • @Luc
    Du gehst vektor 1 Element für Element durch und prüfst, ob das Element in vektor 2 vorhanden ist. Wenn das der Fall ist fügst du das aktuelle Element in vektor 3 ein, ansonsten fügst du eine 0 in vektor 3 ein.

    // Stumpf ohne Sortierung 
    for( auto const& elem : v1 )
    {
       auto p = find( v2.begin(), v.end(), elem );
       if( p != v2.end() ) v3.push_back( elem );
       else                v3.push_back( 0 );
    }
    
    // falls v2 sortiert ist kann man mit lower_bound binär suchen, ob das bei 10 Einträgen sinnvoll ist sei mal dahingestellt. 
    // Man muss aber beachten, dass lower_bound das erste Element zurückgibt, das größer oder gleich groß ist wie
    // das gesuchte Element, dazu braucht man dann noch den Vergleich auf Gleichheit.
    for( auto const& elem : v1 )
    {
       auto p = lower_bound( v2.begin(), v2.end(), elem );
       if( p != v2.end() && *p == elem ) v3.push_back( elem );
       else                              v3.push_back( 0 );
    }
    
    
    

    PS:
    Handgeschriebene Schleifen sollte man möglichst vermeiden. Es gibt in <algorithm> der STL einen Haufen nützliches Zeugs, das einem beim Suchen in Containern hilft. Wenn du bisher noch nichts von der STL gehört hast solltest du dich jetzt damit befassen.



  • @DocShoe Vielen Dank! mit etwas abänderung hab ichs damit zum laufen gebracht:)


  • Mod

    @Luc sagte in Vektoren vergleichen:

    @SeppJ Hast du mir da einen Ansatz? ich hirne seit stunden daran rum und komme auf nichts..

    Du gehst durch beide Vektoren gleichzeitig.

    1. Du vergleichst du beiden aktuellen Werte.
      • Sind sie gleich, schreibst du den entsprechenden Wert raus und gehst in beiden Vektoren um einen Schritt weiter.
      • Sind sie ungleich, dann schreibst du eine 0 raus, und gehst bei dem Vektor mit dem kleineren Element um einen Schritt weiter.
    2. Das führst du so weiter bis du an das Ende eines Vektors kommst. Dann ist der Rest von dem anderen Vektor garantiert nicht mehr in dem fertigen Vektor und du kannst entsprechend Nullen rausschreiben.

    Das ist jetzt im Kopf von mir formuliert und es ist wichtig, dass du das erst einmal verstehst. Wenn man das tatsächlich als Programm hinschreibt, geht das vielleicht auch noch eine Ecke eleganter.

    Das funktioniert natürlich nur, wenn die Vektoren sortiert sind (denk unbedingt nach und verstehe, warum das so ist!). Das hast du zwar nicht ausdrücklich gesagt, aber da das in deinem Beispiel so war, nehme ich das mal als stillschweigende Voraussetzung an. Überhaupt habe ich den Eindruck, dass du uns einige wichtige Voraussetzungen unterschlägst und wahrscheinlich die Aufgabenstellung falsch oder unvollständig wiedergibst. Mit ein paar kleinen Änderungen wäre das nämlich eine richtig schön elegante Standardaufgabenstellung, aber so wie du es hier vorstellst ist, ist es etwas ekelig.



  • @SeppJ Das ist keine Aufgabenstellung, leider nur ein Teil meiner Bachelorarbeit.
    Da frage ich Daten über Hotlinks aus einer Maschine ab. Dieser Hotlink bekommt aber nur alle 50 ms daten mit. Der vollständigere Vektor ist mit daten gefüllt, die man weiss (also ALLEN Daten, auch die, die der Hotlink nicht mitbekommt), der zweite Vektor sind die Daten die der Hotlink gesendet hat.
    Nun sollen die Daten, die der Hotlink nicht erwischt als solche dargestellt werden (als bspw roter Balken über einem Zeitstrahl) und die die er erwischt als andersfarbig. Dafür brauche ich den vergleich der beiden Vektoren.
    An sich ist das alles ziemlich eklig weil der Hotlink eben nicht alles mitbekommt und so erst sortiert und unnötiges aussortiert werden musste und mein Kopf nach 7 stunden einfach auch mal zumacht.


  • Mod

    Woah! Wenn das eine echte Anforderung ist, dann solltest du viel gründlicher vorgehen, besonders bei der genauen Formulierung der Problemstellung. Und da du offensichtlich ziemlich frisch beim Programmieren bist, solltest du dann am besten mit dieser genauen Anforderung hier nachfragen, wie das die erfahrenen Hasen lösen würden. Ob du es glaubst oder nicht, die haben da Spaß dran 🙂

    Was du aber unbedingt vermeiden solltest, ist das sogenannte X-Y-Problem: Du denkst dir selber eine vermeintliche Lösung aus, kommst bei der Umsetzung in Schwierigkeiten, und fragst dann nach der Lösung dieser Schwierigkeit, anstatt nach der Lösung des Problems zu fragen. Denn dann kommen oft entweder Speziallösungen für das wonach du gefragt hast, die dich überhaupt nicht weiterbringen, oder verwirrte Gegenfragen, wozu so eine komische Anforderung gut sein soll.

    In diesem konkreten Fall sehe ich beispielsweise keinen Zusammenhang zwischen deiner Frage und deinem eigentlichen Problem. Beziehungsweise ich sehe schon, wie ein Anfänger von deinem eigentlichen Problem zu deiner hier gestellten Frage kommen könnte, aber ich sehe auch, dass dich eine Lösung zu deiner Frage eigentlich gar nicht weiter bringen würde. Dein eigentliches Problem klingt eher nach einem Fall von irgendeiner Form von Sequence Matching. Was ganz anders ginge.



  • @SeppJ Damit hast sogar du das Problem erkannt das nicht mal meine Firma erkennt: ich habe nicht informatik studiert. Zweites Problem: Dienstag ist abgabe und jetzt muss es halt mal so laufen wie ich mir das gedacht hatte. Und wenn nicht wars das eben.


  • Mod

    Zum eigentlichen Problem: Verstehe ich das richtig? Du hast die Originalsequenz, beispielsweise
    fdbnfkjenfejinvfodenvrjbnfhdbdcwemfp
    und ein paar Teilsequenzen daraus, die du über den Link erhalten hast, z.B.
    fkjenfe, envrjbnf, wemf
    und du möchtest nun folgendes finden:

    fdbn       jinvfod        hdbdc    p
    

    denn:

    fdbnfkjenfejinvfodenvrjbnfhdbdcwemfp
        fkjenfe       envrjbnf     wemf
    fdbn       jinvfod        hdbdc    p
    


  • @SeppJ Ich hab das Original: 0, 1, 3, 12, 13, 14, 15, 16, 19, 23, 35
    Über den Hotlink erhalte ich: 0, 3, 12, 13, 15, 16, 23
    Ich brauche nun die Zahlen 1, 14, 19 und 35 um diesen eine andere Farbe zuzuordnen


  • Mod

    @Luc sagte in Vektoren vergleichen:

    @SeppJ Ich hab das Original: 0, 1, 3, 12, 13, 14, 15, 16, 19, 23, 35
    Über den Hotlink erhalte ich: 0, 3, 12, 13, 15, 16, 23
    Ich brauche nun die Zahlen 1, 14, 19 und 35 um diesen eine andere Farbe zuzuordnen

    Dann war das wie befürchtet ein X-Y-Problem, denn da ist ja nix vonwegen Nullen und so weiter drin. Und ist das wirklich schon sortiert? Denn wenn du das sortiert hast, wäre das auch eine wunderbare Gelegenheit gewesen, an der Stelle nach den Matches zu suchen.

    Aber mal angenommen, dass du wirklich mit zwei sortierten Vektoren in dieser Form anfängst, ist das ein Einzeiler (hier die Zeile 11, der Rest ist nur Drumrum, damit du ein komplettes Programm hast):

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <iterator>
    using namespace std;
    
    int main() {
      vector<int> vector1 = {0, 1, 3, 21, 22, 23, 24, 25};
      vector<int> vector2 = {0, 1, 3, 22, 24, 25};
      vector<int> difference;
      set_difference(vector1.begin(), vector1.end(), vector2.begin(), vector2.end(), back_inserter(difference));
      cout  << "Unterschiede: ";
      for (auto i: difference)
          cout << i << ' ';
    }
    

    https://ideone.com/jHs015

    Mögliche Erklärungen, was hinter set_difference an Code stehen könnte kannst du auf diesen Seiten finden:
    http://www.cplusplus.com/reference/algorithm/set_difference/
    https://en.cppreference.com/w/cpp/algorithm/set_difference

    Aber das ist im Prinzip nichts anderes als ich die oben erklärt hatte:

    Du gehst durch beide Vektoren gleichzeitig.

    1. Du vergleichst du beiden aktuellen Werte.
      • Sind sie gleich, schreibst du den entsprechenden Wert raus und gehst in beiden Vektoren um einen Schritt weiter.
      • Sind sie ungleich, dann schreibst du eine 0 raus, und gehst bei dem Vektor mit dem kleineren Element um einen Schritt weiter.
    2. Das führst du so weiter bis du an das Ende eines Vektors kommst. Dann ist der Rest von dem anderen Vektor garantiert nicht mehr in dem fertigen Vektor und du kannst entsprechend Nullen rausschreiben.

    bloß ohne die Nullen, über die ich mich ja auch schon gewundert hatte und die ja wohl gar nicht nötig waren.



  • @SeppJ Ja die Vektoren sind bereits sortiert, dabei handelt es sich um CNC-Codezeilen.
    Die Lösung die oben genannt wurde funktioniert eigentlich, nur die zuordnung zur Darstellung klappt nicht, warum auch immer.
    Das mit den Nullen ist auch nur ein Platzhalter, Statt dem "Schreibe nullen in einen dritten Vektor" steht hier am ende dann sowas wie "Ordne dem Block die und die Farbe zu".



  • @Luc Code.
    Eingabe?
    Erwartete Ausgabe?
    Tatsächliche Ausgabe?


Anmelden zum Antworten