Beliebige Vectorelemente löschen
-
Hallo zusammen,
ich suche eine effizient Möglichkeit folgendes Szenario umzusetzen:
Sei vec ein beliebiger Vector.
foreach v Element vec { do something with v; del(vec); } del(vector<T> &vec) { löschen von beliebig vielen Elementen. Es könnten alle oder kein Element gelöscht werden. }Ich hab schon vesucht den Iterator von vec der del-Metzhode mitzugeben, um ihn beim Löschen zu aktuallisieren. Ohne Erfolg.
In meiner jetzigen Implementierung lösche ich nicht, sonder merke mir die Elemente in einem Hilfsvektor und mache ein continue in der for-Schleife. Das dauert aber alles zu lange, da keine vec keine trivialen Datenstruktruren hält und alleine die Checks sehr lange dauern.
Ich brauche also eine funktionierende foreach-Schleife, auch wenn innerhalb einer Iteration beliebige Elemente gelöscht werden können.
Vielen Dank schon mal.
-
Iteratoren auf den vector können ungültig werden, sobald Du den vector veränderst. Welches Element, ist hierbei egal.
Wenn Du den Iterator mitgibst, um ihn zu aktualisieren (ich nehme an, durch den Rückgabewert von vector::erase), hast Du da eine Referenz übergeben?
Am gängigsten ist die Methode, die zu löschenden Elemente nach hinten zu sortieren, und dann den Range-Erase aufzurufen:
vec.erase( std::remove_if( vec.begin(), vec.end(), BEDINGUNG ), vec.end() );
-
Sorry, ich verstehe nicht ganz, was du meinst. Soll
del()willkürlich viele Elemente löschen? Was planst du genau?Falls du einfach durchiterieren willst und bei gewissen Bedingungen das aktuelle Element entfernen willst, kannst du folgendes tun:
std::vector<Type> Vec; // Vec füllen for (std::vector<Type>::iterator i = Vec.begin; i != Vec.end; ++i) { if (Condition) i = Vec.erase(i); // Der Iterator geht weiter auf das nächste gültige Element }
-
Nexus schrieb:
std::vector<Type> Vec; // Vec füllen for (std::vector<Type>::iterator i = Vec.begin; i != Vec.end; ++i) { if (Condition) i = Vec.erase(i); // Der Iterator geht weiter auf das nächste gültige Element }std::vector<Type> Vec; // Vec füllen for (std::vector<Type>::iterator i = Vec.begin; i != Vec.end; ) { if (Condition) i = Vec.erase(i); // Der Iterator geht weiter auf das nächste gültige Element else ++i; }
-
Hm, meine Version erfüllt aber den Zweck...?
Zumindest abgesehen davon, dass beibegin()undend()die Klammern fehlen
-
Nexus schrieb:
Hm, meine Version erfüllt aber den Zweck...?
Nicht ganz: Wenn ein Element gelöscht wird, wird der Iterator auf das dem gelöschten folgende Element gesetzt. Das ++i der for-Schleife setzt ihn dann nochmal eins weiter, womit Du ein Element "übersiehst".
-
LordJaxom schrieb:
Nicht ganz: Wenn ein Element gelöscht wird, wird der Iterator auf das dem gelöschten folgende Element gesetzt. Das ++i der for-Schleife setzt ihn dann nochmal eins weiter, womit Du ein Element "übersiehst".
Danke, habs jetzt auch gerade rausgefunden

Zuerst hab ich mir es überlegt, und da bin ich eigentlich auf KasFs Lösung gekommen. Dann wollte ich es natürlich "zur Sicherheit" an einem Code-Beispiel testen, und dummerweise hatte ich per Zufall bei meiner Version ein Beispiel genommen, das gerade funktionierte (Deshalb auch die Edits, zuerst hatte ich KasF noch zugestimmt)...
Vielleicht sollte ich dem Verstand doch ein bisschen mehr vertrauen als dem Compiler

-
Nexus schrieb:
Sorry, ich verstehe nicht ganz, was du meinst. Soll
del()willkürlich viele Elemente löschen? Was planst du genau?Leider ja.
Es handelst sich um ein kombinatorisches Problem.
Mein Pseudo-Code:
[img=http://img46.imageshack.us/img46/399/snap1pu4.th.png]Daher bringt eine Sortierung vor "foreach" nichts.
Ich hab also den originären Vector und einen Vector indem die zu löschenden Elemente stecken.
-
Mein Versuch mit Iterator sah ungefähr so aus:
void del(vector<int> &vec, vector<int>::iterator &it) { if(vec.size() == 6) { it=vec.erase(vec.begin()); it=vec.erase(vec.begin()); it=vec.erase(vec.begin()); it=vec.erase(vec.begin()); it=vec.erase(vec.begin()); it=vec.erase(vec.begin()); } } int main() { vector<int> vec; vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5); vec.push_back(6); vector<int>::iterator iter;// = vec.begin(); for(iter = vec.begin(); iter != vec.end(); iter++) { cout << *iter << endl; del(vec, iter); } }
-
Upps.
So gehts schon besser:int main() { vector<int> vec; vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5); vec.push_back(6); vector<int>::iterator iter;// = vec.begin(); for(iter = vec.begin(); iter != vec.end(); iter++) { cout << *iter << endl; del(vec, iter); if(iter == vec.end()){ break; } } }