Se ad esempio si dispone di std::vector<MyClass>
, dove MyClass
ha un metodo pubblico: bool isTiredOfLife()
, come si rimuovono gli elementi che restituiscono true?Come rimuovere elementi di un vettore std :: in base ad alcune proprietà degli elementi?
risposta
preferisco remove_if
v.erase(remove_if(v.begin(), v.end(),
mem_fun_ref(&MyClass::isTiredOfLife)),
v.end());
remove_if
restituisce un puntamento iteratore dopo l'ultimo elemento che è ancora nella sequenza. erase
cancella tutto dal primo all'ultimo argomento (entrambi gli iteratori).
Utilizzare remove_if è il modo "giusto" per farlo. Fare attenzione a NON utilizzare un iteratore per scorrere e cancellare, poiché la rimozione di elementi invalida l'iteratore. In effetti, qualsiasi esempio che usa erase() come metodo principale è una cattiva idea sui vettori, perché cancella è O (n), che renderà il tuo algoritmo O (n^2). Questo dovrebbe essere un algoritmo O (n).
È probabile che il metodo che di seguito sia più veloce di remove_if ma, diversamente da remove_if, NON conserverà l'ordine relativo degli elementi. Se ti interessa mantenere l'ordine (cioè il tuo vettore è ordinato), usa remove_if, come nella risposta sopra. Se non si cura di ordine, e se il numero di elementi da cancellare è in genere meno di un quarto del vettore, questo metodo è probabile che sia più veloce:
for(size_t i = 0; i < vec.size();)
if(vec[i].isTiredOfLife())
{
vec[i] = vec.back();
vec.pop_back();
}
else
++i;
D'oh. L'ho dimenticato. È anche in grassetto nella pagina che ho linkato. : o Ho cancellato il mio post, quindi nessuno lo usa. – Bernard
Non riordinerà gli elementi nel vettore? Supponendo che, per esempio, il vettore di input sia ordinato, il vettore di output no, l'ultimo elemento prenderà la posizione del primo elemento eliminato. –
Potresti voler aggiornare la tua risposta per non fare più riferimento a Bernard. –
I in merito dimenticato remove_if() +1 . –
Molto interessante. Mai visto prima +1 – Bernard
Grazie, ha funzionato. –