[STL] Vector iterator an Position springen
-
Dann nimm's halt aus Boost. Daher kommt der Kram ja ursprünglich.
-
Klaus82 schrieb:
ein kleines Programm zusammengestrickt, was die Anforderungen in abgewandelter Form erfüllt.
Das ist leider Murks.
Fehler:
- Du überspringst ggf ein Element, ohne es überprüft zu haben.
- Du dekrementierst einen Iterator, der ggf schon auf das erste Element zeigt.Komisch:
- swap bringt dir in deinem Fall gegenüber einer einfachen Zuweisung nichts.
- Wozu inkludierst du <iterator>?Schade. Du hast da mit dem Überspringen übrigens einen Fehler gemacht, vor dem ich auf Seite 4 schon am 23.5. um 10:57 Uhr gewarnt habe.
-
Ich möchte auch nocheinmal den Hinweis von Seite 4 von SeppJ und Seldon zu remove_if erneuern. Das macht genau das, was du versuchst, nur ohne Fehler.
Damit kannst du deine gesamte handgestrickte Schleife in Zeile 43 bis 54 durch einen Einzeiler ersetzen.
-
krümelkacker schrieb:
Fehler:
- Du überspringst ggf ein Element, ohne es überprüft zu haben.Oh ja! Ich war so auf das
move
fixiert, dass wir doch nicht benötigen, dass ich dachte es sei jetzt überholt und ich könnte getrosti
erhöhen.
Aber ich muss ja noch das Element prüfen, mit dem ich getauscht habe und dazu darf ich erstmal nicht erhöhen!krümelkacker schrieb:
- swap bringt dir in deinem Fall gegenüber einer einfachen Zuweisung nichts.
Das verstehe ich nicht. Was ist in diesem Zusammenhang
eine einfache Zuweisung
?Schlußendlich muss ich sagen, dass ich nicht mal mehr verstehe, warum wir
swappen
odermoven
[1] wollten. Es reicht doch wirklich folgendes:iter = v.begin(); for(unsigned int i = 0; i < num_ints;) { if(delete_element(v[i])) { l.push_back(v[i]); v.erase(iter+i); --num_ints; } else // do something else with the element v[i] ++i; }
Klappe zu, Affe tot.
Wobei ich hier nochmal konkret nachfragen muss, wie sich das mit dem Indexzugriff verhält. Wenn ich über einen Iterator zugreife, so steht ja zu erase, dass ein Iterator zurückgegeben wird, der auf das folgende Element zeigt.
Wenn ich jetzt aber ein Element lösche, dann müssen die anderen alle 'nach oben nachrücken', oder? D.h. ich habe eine Indexverschiebung
Wenn ich also i nicht bei jedem Schleifendurchlauf erhöhe, so wird i dadurch 'erhöht', dass ein Element gelöscht wird. Also das Element i+1 ist jetzt i und (ich erhöhe i nicht) so prüfe ich eben das nächste Element.Gruß,
Klaus.[1] Immer diese denglischen Begriffsbildungen.
-
Klaus82 schrieb:
krümelkacker schrieb:
- swap bringt dir in deinem Fall gegenüber einer einfachen Zuweisung nichts.
Das verstehe ich nicht. Was ist in diesem Zusammenhang
eine einfache Zuweisung
?int a = 23; int b = 42; //swap(a,b); // <- Vertauschung a = b; // <- Zuweisung
Da du b quasi nicht mehr brauchst, reicht die Zuweisung. In beiden Fällen bekommt a den Wert, den b hatte.
Klaus82 schrieb:
Schlußendlich muss ich sagen, dass ich nicht mal mehr verstehe, warum wir
swappen
odermoven
[1] wollten. Es reicht doch wirklich folgendes:iter = v.begin(); for(unsigned int i = 0; i < num_ints;) { if(delete_element(v[i])) { l.push_back(v[i]); v.erase(iter+i); --num_ints; } else // do something else with the element v[i] ++i; }
Klappe zu, Affe tot.
Klaus82 schrieb:
Wenn ich jetzt aber ein Element lösche, dann müssen die anderen alle 'nach oben nachrücken', oder?
Ja sicher. Deswegen ist das Löschen eines einzelnen Elements aus der Mitte auch eine doofe Idee und deswegen hast du ja auch Tipps bekommen, wie du es besser machen könntest!
-
Hi,
krümelkacker schrieb:
Klaus82 schrieb:
Wenn ich jetzt aber ein Element lösche, dann müssen die anderen alle 'nach oben nachrücken', oder?
Ja sicher. Deswegen ist das Löschen eines einzelnen Elements aus der Mitte auch eine doofe Idee und deswegen hast du ja auch Tipps bekommen, wie du es besser machen könntest!
Ich glaube das bringt bei mir zur Zeit noch nichts, da ich einfach zu wenig Ahnung von STL habe.
Ich kann z.B. überhaupt nicht abschätzen, wieviel Aufwand etwas darstellt. Wenn z.B. löschen in der Mitte eines Vektors eine doofe Idee ist, wieso ist es dann weniger umständlich das Element ans Ende zu verschieben und dann alle Elemente gesammelt am Ende zu löschen.
Sicher, das Löschen am Ende erscheint mir kompakter, aber allein das Verschieben ist doch auch Aufwand.Aus dem Grund muss ich erstmal viel lesen gehen ... hab ja jetzt den C++ Primer und laut Vorwort, wird auch direkt auf die STL eingegangen. Schließlich sei es unsinnig alles primitiv zu programmieren, nur um dann am Ende zu sagen: Wir müssen das Rad nicht neu erfinden, sondern uns lediglich der STL bedienen.
Vielleicht sehe ich dann klarer.
Momentan habe ich nur das Gefühl ich drehe mich im Kreis.
Auf jeden Fall danke an alle, die so lange durchgehalten haben.
Viele Grüße,
Klaus.
-
Klaus82 schrieb:
Ich kann z.B. überhaupt nicht abschätzen, wieviel Aufwand etwas darstellt. Wenn z.B. löschen in der Mitte eines Vektors eine doofe Idee ist, wieso ist es dann weniger umständlich das Element ans Ende zu verschieben und dann alle Elemente gesammelt am Ende zu löschen.
Ans Ende schieben sollst du sie gar nicht. Das war nur eine Idee vom Pi mit dem swap. Sagte ich ja, dass das unnötig ist. Das Ding ist, wenn du erase für ein einziges Element in der Mitte durchführst, müssen die dahinter liegenden nachrücken und das kostet. Da die Reihenfolge im Vektor bei dir aber gar nicht wichtig zu sein scheint, kannst du auch einfach das letzte Element an die Stelle kopieren, die du sonst gelöscht hättest. Also, statt
soll weg | V +---+---+---+---+---+ | H | e | l | l | o | +---+---+---+---+---+ / / / / / / / / / +---+---+---+---+ | H | l | l | o | +---+---+---+---+
machst du einfach
|<- gültig bis +---+---+---+---+---+ | H | e | l | l | o | +---+---+---+---+---+ | +-----------+ | V |<- gültig bis +---+---+---+---+---+ | H | o | l | l | o | +---+---+---+---+---+
Hinterher dann die Dinger am Ende, die eh nicht mehr gültig sind, mit einem Rutsch entfernen und fertig ist die Laube.
-
Hi,
krümelkacker schrieb:
Da die Reihenfolge im Vektor bei dir aber gar nicht wichtig zu sein scheint, kannst du auch einfach das letzte Element an die Stelle kopieren, die du sonst gelöscht hättest.
Ah, ich glaube jetzt verstehe ich was du meinst. Also nicht das Element im Vektor selbst verschieben, sondern lediglich den Inhalt des Elements kopieren.
Etwas in diesem Stil:
vecttor<int> v; // ... v wird gefüllt vector<int>::iterator iter = --(v.end()); // iterator auf letztes Element unsigned int num_v = v.size(); for(unsigned int i = 0; i < num_v;) { if('soll Element i gelöscht werde') { int last_position = std::distance(v.begin(),iter); v[i] = v[last_position]; --num_v; --iter; // <--- noch zu prüfen, falls iter zu v.begin() wird } else { ++i; } } v.erase(iter,v.end());
So ungefähr?
Gruß,
Klaus.P.S.: Danke für die schönenen ASCII Zeichnungen!
-
//Fehler .....
-
Das geht noch einfacher und "korrekter":
vector<int> v; // ... v wird gefüllt unsigned gueltig = v.size(); for (unsigned i=0; i<gueltig;) { if('soll i-tes Element gelöscht werden?') { --gueltig; v[i] = v[gueltig]; } else { ++i; } } v.erase(v.begin()+gueltig,v.end());
Für statistische Simulationen ist std::rand wohl auch keine gute Idee. Da gibt es qualitativ hochwertigere Pseudozufallszahlengeneratoren. Siehe Boost.Random