Domanda

Stavo esaminando la documentazione dell'API per il vettore stl e ho notato che non esisteva alcun metodo nella classe vettoriale che consentisse la rimozione di un elemento con un determinato valore.Sembra un'operazione comune e sembra strano che non ci sia un modo integrato per farlo.

È stato utile?

Soluzione

std::remove in realtà non cancella l'elemento dal contenitore, ma restituisce il nuovo iteratore finale a cui può essere passato container_type::erase per eseguire la VERA rimozione degli elementi extra che ora si trovano alla fine del contenitore:

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());

Altri suggerimenti

Se vuoi rimuovere UN elemento, quanto segue sarà un po' più efficiente.

std::vector<int> v;


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

oppure puoi evitare le spese generali legate allo spostamento degli articoli se l'ordine non ti interessa:

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();
}

Utilizza il metodo globale std::remove con l'iteratore Begin ed End, quindi utilizza std::vettore.erase per rimuovere effettivamente gli elementi.

Collegamenti alla documentazione
std::rimuovi http://www.cppreference.com/cppalgorithm/remove.html
std::vettore.erase http://www.cppreference.com/cppvettore/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

Grazie a Jim Buck per aver sottolineato il mio errore.

Le altre risposte spiegano come farlo bene, ma ho pensato di sottolineare anche che non è proprio strano che questo non sia nell'API vettoriale:è inefficiente, la ricerca lineare del valore nel vettore, seguita da una serie di operazioni di copia per rimuoverlo.

Se stai eseguendo questa operazione in modo intensivo, può valere la pena considerare std::set per questo motivo.

Se hai un vettore non ordinato, puoi semplicemente scambiarlo con l'ultimo elemento del vettore resize().

Con un contenitore ordinato, la soluzione migliore è ‍ std::vector::erase().Tieni presente che esiste un std::remove() definito in <algorithm>, ma questo in realtà non esegue la cancellazione.(Leggere attentamente la documentazione).

Una soluzione più breve (che non obbliga a ripetere il nome del vettore 4 volte) sarebbe quella di utilizzare Boost:

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

// ...

boost::remove_erase(vec, int_to_remove);

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

Guarda anche std::rimuovi_if poter usare un predicato...

Ecco l'esempio dal link sopra:

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".

Da c++20:

Introdotta una funzione non membro std::erase, che accetta il vettore e il valore da rimuovere come input.

ex:

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

Se vuoi farlo senza extra include:

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;
            }
        }
    }
}

Esistono due modi con cui è possibile utilizzare per cancellare un elemento in particolare.Prendiamo un vettore

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) Modo non efficiente: Anche se sembra abbastanza efficiente, ma non lo è perché la funzione di cancellazione elimina gli elementi e sposta tutti gli elementi verso sinistra di 1.quindi la sua complessità sarà O(n^2)

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

2) Modo efficiente (CONSIGLIATO) :È anche noto come CANCELLARE - RIMUOVERE gli idiomi .

  • std::remove trasforma l'intervallo specificato in un intervallo con tutti gli elementi che si confrontano in modo diverso dall'elemento specificato spostati all'inizio del contenitore.
  • Quindi, in realtà non rimuovere gli elementi corrispondenti.Ha semplicemente spostato la non corrispondenza all'inizio e fornisce un iteratore alla nuova fine valida.Richiede solo complessità O(n).

l'output dell'algoritmo di rimozione è:

10 20 30 50 40 50 

poiché il tipo restituito di rimozione è l'iteratore fino alla nuova fine di tale intervallo.

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

Ora usa la funzione di cancellazione del vettore per eliminare gli elementi dalla nuova estremità alla vecchia estremità del vettore.Richiede tempo O(1).

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

quindi questo metodo funziona in O(n)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top