Element aus vektor löschen



  • Hallo,

    Ich möchte einen Vektor durchsuchen und bei einem Treffer die Vektorstelle löschen.
    Ich würde gerne mal wissen ob das hier so falsch funktioniert wie ich es mir gerade vorstelle:

    if(files.at(i).find(pattern) == string::npos) {
    			files.erase(files.begin()+i);
    		}
    

    Das würde jetzt doch den vektor durchsuchen, und bei einem Fund danach ein objekt überspringen richtig?

    also ich suche nach "c" und habe einen vektor:
    a
    b
    c <- Fund --> lösche (begin + 2)

    "neuer" Vektor, Suche geht weiter:
    a
    b
    d
    e << einstieg weil i mittlerweile 3 ist. Das d wurde übersprungen.
    f

    ist das richtig? und btw, wie würd mans richtig machen? 🙂

    Gruß,
    Chris



  • Nein, das sieht ziemlich falsch aus.
    Es gibt das Erase-Remove-Idiom:

    std::vector<Foo> vec = {...};
    
    vec.erase(std::remove(std::begin(vec), std::end(vec), value), std::end(vec));
    

    Wahlweise auch mit Remove_If und einem Funktor/Lambda.



  • alles klar, danke! 🙂



  • cl90 schrieb:

    if(files.at(i).find(pattern) == string::npos) {
    			files.erase(files.begin()+i);
    		}
    

    Das würde jetzt doch den vektor durchsuchen, und bei einem Fund danach ein objekt überspringen richtig?

    Das wäre sehr ineffizient, wenn du das in einer Schleife über i machen würdest, weil jedes mal, wo ein Element gelöscht wird, alle anderen nachrücken müssen. Das kann man auch in einem Rutsch vernünftig machen, wie schon angedeutet wurde:

    files.erase(
            std::remove_if(files.begin(),files.end(),[&](string const& x){
                return x.find(pattern) != string::npos;
            }),
            files.end());
    

    Hier wird jedes Element, was übrig bleiben soll, per remove_if höchstens einmal auf einen neuen Platz verschoben. Der Kram, der am Ende steht und nicht mehr benötigt wird, wird mit einer einzigen Aktion per erase gelöscht.



  • je nach Container, könnte es so ein remove_if als Elementfunktion geben. Falls man z.B. eine std::list vor sich hat, sollte man lieber std::list<>::remove_if nehmen. Da werden wahrscheinlich nur ein paar Zeiger umgebogen, statt dass da Elemente von einem Listenknoten in einen anderen Listenknoten kopiert werden.


Anmelden zum Antworten