Wie entferne ich ein Element aus einem STL-Vektor mit einem bestimmten Wert?

StackOverflow https://stackoverflow.com/questions/39912

  •  09-06-2019
  •  | 
  •  

Frage

Ich habe mir die API-Dokumentation für stl vector angesehen und festgestellt, dass es in der Vektorklasse keine Methode gibt, die das Entfernen eines Elements mit einem bestimmten Wert ermöglicht.Dies scheint ein üblicher Vorgang zu sein, und es erscheint seltsam, dass es hierfür keine integrierte Möglichkeit gibt.

War es hilfreich?

Lösung

std::remove löscht das Element nicht wirklich aus dem Container, gibt aber den neuen Enditerator zurück, an den übergeben werden kann container_type::erase um die WIRKLICHE Entfernung der zusätzlichen Elemente durchzuführen, die sich jetzt am Ende des Containers befinden:

std::vector<int> vec;
// .. put in some values ..
int int_to_remove = n;
vec.erase(std::remove(vec.begin(), vec.end(), int_to_remove), vec.end());

Andere Tipps

Wenn Sie entfernen möchten ein Artikel, das Folgende wird etwas effizienter sein.

std::vector<int> v;


auto it = std::find(v.begin(), v.end(), 5);
if(it != v.end())
    v.erase(it);

Oder Sie können den Mehraufwand für den Transport der Artikel vermeiden, wenn die Reihenfolge für Sie keine Rolle spielt:

std::vector<int> v;

auto it = std::find(v.begin(), v.end(), 5);

if (it != v.end()) {
  using std::swap;

  // swap the one to be removed with the last element
  // and remove the item at the end of the container
  // to prevent moving all items after '5' by one
  swap(*it, v.back());
  v.pop_back();
}

Verwenden Sie die globale Methode std::remove mit dem Anfangs- und End-Iterator 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

std::vector<int> v;
v.push_back(1);
v.push_back(2);

//Vector should contain the elements 1, 2

//Find new end iterator
std::vector<int>::iterator newEnd = std::remove(v.begin(), v.end(), 1);

//Erase the "removed" elements.
v.erase(newEnd, v.end());

//Vector should now only contain 2

Vielen Dank an Jim Buck für den Hinweis auf meinen Fehler.

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 im Vektor nach dem Wert, gefolgt von einer Menge Kopiervorgängen, um ihn zu entfernen.

Wenn Sie diesen Vorgang intensiv ausführen, kann es sich aus diesem Grund lohnen, stattdessen std::set in Betracht zu ziehen.

Wenn Sie einen unsortierten Vektor haben, können Sie ihn dann einfach mit dem letzten Vektorelement austauschen resize().

Mit einem geordneten Container sind Sie mit ‍ am besten dran std::vector::erase().Beachten Sie, dass es eine gibt std::remove() definiert in <algorithm>, aber das löscht nicht wirklich.(Lesen Sie die Dokumentation sorgfältig durch).

Eine kürzere Lösung (die Sie nicht dazu zwingt, den Vektornamen viermal zu wiederholen) wäre die Verwendung von Boost:

#include <boost/range/algorithm_ext/erase.hpp>

// ...

boost::remove_erase(vec, int_to_remove);

Sehen http://www.boost.org/doc/libs/1_64_0/libs/range/doc/html/range/reference/algorithms/new/remove_erase.html

Siehe auch std::remove_if ein Prädikat verwenden können...

Hier ist das Beispiel aus dem obigen Link:

vector<int> V;
V.push_back(1);
V.push_back(4);
V.push_back(2);
V.push_back(8);
V.push_back(5);
V.push_back(7);

copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
    // The output is "1 4 2 8 5 7"

vector<int>::iterator new_end = 
    remove_if(V.begin(), V.end(), 
              compose1(bind2nd(equal_to<int>(), 0),
                       bind2nd(modulus<int>(), 2)));
V.erase(new_end, V.end()); [1]

copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
    // The output is "1 5 7".

Aus c++20:

Eine Nicht-Mitgliedsfunktion eingeführt std::erase, das den zu entfernenden Vektor und Wert als Eingaben verwendet.

ex:

std::vector<int> v = {90,80,70,60,50};
std::erase(v,50);

Wenn Sie es ohne Extras machen möchten, beinhaltet:

vector<IComponent*> myComponents; //assume it has items in it already.
void RemoveComponent(IComponent* componentToRemove)
{
    IComponent* juggler;

    if (componentToRemove != NULL)
    {
        for (int currComponentIndex = 0; currComponentIndex < myComponents.size(); currComponentIndex++)
        {
            if (componentToRemove == myComponents[currComponentIndex])
            {
                //Since we don't care about order, swap with the last element, then delete it.
                juggler = myComponents[currComponentIndex];
                myComponents[currComponentIndex] = myComponents[myComponents.size() - 1];
                myComponents[myComponents.size() - 1] = juggler;

                //Remove it from memory and let the vector know too.
                myComponents.pop_back();
                delete juggler;
            }
        }
    }
}

Es gibt zwei Möglichkeiten, wie Sie ein Element gezielt löschen können.Nehmen wir einen Vektor

std :: vector < int > v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(40);
v.push_back(50);

1) Nicht effizienter Weg: Dies scheint zwar recht effizient zu sein, liegt aber nicht daran, dass die Löschfunktion die Elemente löscht und alle Elemente um 1 nach links verschiebt.also wird seine Komplexität O(n^2) sein

std :: vector < int > :: iterator itr = v.begin();
int value = 40;
while ( itr != v.end() )
{
   if(*itr == value)
   { 
      v.erase(itr);
   }
   else
       ++itr;
}

2) Effiziente Methode (EMPFOHLEN) :Es ist auch bekannt als ERASE – Redewendungen ENTFERNEN .

  • std::remove wandelt den angegebenen Bereich in einen Bereich um, in dem alle Elemente, die mit dem angegebenen Element ungleich sind, an den Anfang des Containers verschoben werden.
  • Entfernen Sie also nicht die übereinstimmenden Elemente.Es hat lediglich das Nichtübereinstimmende nach „Starting“ verschoben und einen Iterator zu einem neuen gültigen Ende hinzugefügt.Es erfordert lediglich O(n)-Komplexität.

Die Ausgabe des Remove-Algorithmus ist:

10 20 30 50 40 50 

Der Rückgabetyp von „remove“ ist ein Iterator zum neuen Ende dieses Bereichs.

template <class ForwardIterator, class T>
  ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val);

Verwenden Sie nun die Löschfunktion des Vektors, um Elemente vom neuen Ende bis zum alten Ende des Vektors zu löschen.Es erfordert O(1) Zeit.

v.erase ( std :: remove (v.begin() , v.end() , element ) , v.end () );

also funktioniert diese Methode in O(n)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top