Ich habe mir die API-Dokumentation für stl vector angesehen und festgestellt, dass es für die Vektorklasse keine Methode gibt, mit der ein Element mit einem bestimmten Wert entfernt werden kann. Dies scheint eine übliche Operation zu sein, und es scheint seltsam, dass es keine eingebaute Möglichkeit gibt, dies zu tun.
145
Antworten:
std::remove
löscht das Element nicht tatsächlich aus dem Container, sondern gibt den neuen Enditerator zurück, an den übergeben werden kann, umcontainer_type::erase
die zusätzlichen Elemente, die sich jetzt am Ende des Containers befinden, WIRKLICH zu entfernen:quelle
vec.end()
garantiert, dass es auf beiden Seiten des Aufrufs von gleich iststd::remove
? Es scheint mir sicher zu sein, andere Teile des Webs zu lesen, aber es sollte klar angegeben werden.vec.end()
muss nicht dasselbe sein. es muss nur richtig sein (was es ist).vec.end()
muss gleich sein, aber das ist in Ordnung, weilstd::remove
es nichts ändert. Wenn es geändert würde (und den alten Wert ungültig macht), würde es ein Problem geben: Die Reihenfolge der Auswertung der Parameter ist nicht spezifiziert und daher würden Sie nicht wissen, ob der zweitevec.end()
zum Zeitpunkt seiner Verwendung noch gültig ist. Der Grund, warum es dasselbe ist, ist einfach: Esstd::remove
ändert nicht die Größe des Containers, sondern verschiebt nur den Inhalt.std::remove
nur ein Argument an; das istconst char *_Filename
. Welche Methode muss ich aufrufen?remove
, die eine Datei löscht. Sie müssen einschließen,<algorithm>
um auf die Version zuzugreifen, dieremove
sich mit Containern befasst.Wenn Sie ein Element entfernen möchten , ist das Folgende etwas effizienter.
oder Sie können den Aufwand für das Verschieben der Artikel vermeiden, wenn die Bestellung für Sie keine Rolle spielt:
quelle
Verwenden Sie die globale Methode std :: remove mit dem Start- und Enditerator und verwenden Sie dann std :: vector.erase, um die Elemente tatsächlich zu entfernen.
Dokumentationslinks
std :: remove http://www.cppreference.com/cppalgorithm/remove.html
std :: vector.erase http://www.cppreference.com/cppvector/erase.html
Vielen Dank an Jim Buck für den Hinweis auf meinen Fehler.
quelle
Die anderen Antworten behandeln, wie man das gut macht, aber ich dachte, ich möchte auch darauf hinweisen, dass es nicht wirklich seltsam ist, dass dies nicht in der Vektor-API enthalten ist: Es ist eine ineffiziente, lineare Suche durch den Vektor nach dem Wert, gefolgt von einer Reihe zu kopieren, um es zu entfernen.
Wenn Sie diesen Vorgang intensiv ausführen, kann es aus diesem Grund sinnvoll sein, stattdessen std :: set in Betracht zu ziehen.
quelle
Wenn Sie einen unsortierten Vektor haben, können Sie dann einfach mit dem letzten Vektorelement tauschen
resize()
.Mit einem geordneten Behälter, werden Sie am besten dran sein mit
std::vector::erase()
. Beachten Sie, dass instd::remove()
definiert ist<algorithm>
, das Löschen jedoch nicht durchgeführt wird. (Lesen Sie die Dokumentation sorgfältig durch).quelle
Eine kürzere Lösung (die Sie nicht zwingt, den Vektornamen viermal zu wiederholen) wäre die Verwendung von Boost:
Siehe http://www.boost.org/doc/libs/1_64_0/libs/range/doc/html/range/reference/algorithms/new/remove_erase.html
quelle
Ab c ++ 20 :
Es wurde eine Nichtmitgliedsfunktion eingeführt
std::erase
, die den zu entfernenden Vektor und Wert als Eingaben verwendet.Ex:
quelle
map::erase
!Siehe auch std :: remove_if , um ein Prädikat verwenden zu können ...
Hier ist das Beispiel aus dem obigen Link:
quelle
Wenn Sie es ohne zusätzliche Funktionen tun möchten, gehören:
quelle
Es gibt zwei Möglichkeiten, mit denen Sie ein Element besonders löschen können. Nehmen wir einen Vektor
1) Nicht effizienter Weg: Obwohl es ziemlich effizient zu sein scheint, liegt es nicht daran, dass die Löschfunktion die Elemente löscht und alle Elemente um 1 nach links verschiebt, sodass ihre Komplexität O (n ^ 2) ist.
2) Effizienter Weg (EMPFOHLEN) : Es wird auch als ERASE - REMOVE-Redewendungen bezeichnet .
Die Ausgabe des Entfernungsalgorithmus lautet:
Als Rückgabetyp entfernt wird der Iterator zum neuen Ende dieses Bereichs.
Verwenden Sie nun die Löschfunktion des Vektors, um Elemente vom neuen zum alten Ende des Vektors zu löschen. Es benötigt O (1) Zeit.
Diese Methode funktioniert also in O (n).
quelle
* *
* *
C ++ 20 bietet jetzt eine einfache Möglichkeit, dies zu tun. Es wird so einfach wie:
Sie sollten std :: erase und std :: erase_if auschecken .
Es werden nicht nur alle Elemente des Werts (hier '0') entfernt, sondern auch in O (n) -Zeitkomplexität. Welches ist das Beste, was Sie bekommen können.
Wenn Ihr Compiler C ++ 20 nicht unterstützt, sollten Sie das Erase-Remove-Idiom verwenden :
quelle