Ho uno std :: vector <int> e voglio eliminare l'ennesimo elemento. Come lo faccio?
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
vec.erase(???);
Ho uno std :: vector <int> e voglio eliminare l'ennesimo elemento. Come lo faccio?
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
vec.erase(???);
Risposte:
Per eliminare un singolo elemento, puoi fare:
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
// Deletes the second element (vec[1])
vec.erase(vec.begin() + 1);
Oppure, per eliminare più di un elemento contemporaneamente:
// Deletes the second through third elements (vec[1], vec[2])
vec.erase(vec.begin() + 1, vec.begin() + 3);
operator+
è necessariamente definito per gli iteratori su altri tipi di container, come (non puoi farlo su un , devi usarlo per quello)list<T>::iterator
list.begin() + 2
std::list
std::advance
std::find_if
Il metodo di cancellazione su std :: vector è sovraccarico, quindi è probabilmente più chiaro chiamare
vec.erase(vec.begin() + index);
quando vuoi solo cancellare un singolo elemento.
vec.begin()
quale è valido.
vec.erase(0)
non funziona, ma vec.erase(vec.begin()+0)
(o senza +0) funziona. Altrimenti non ricevo alcuna chiamata di funzione corrispondente, motivo per cui sono venuto qui
vec.erase(0)
può effettivamente compilare se 0
viene interpretato come costante del puntatore null ...
template <typename T>
void remove(std::vector<T>& vec, size_t pos)
{
std::vector<T>::iterator it = vec.begin();
std::advance(it, pos);
vec.erase(it);
}
template <typename T> void remove(std::vector<T>& vec, size_t pos) { vec.erase(vec.begin + pos); }
non sto dicendo che sia meglio, semplicemente chiedendo per interesse personale e per restituire il miglior risultato che questa domanda potrebbe ottenere.
vector<T>::iterator
è un iteratore ad accesso casuale, la tua versione va bene e forse un po 'più chiara. Ma la versione pubblicata da Max dovrebbe funzionare bene se si cambia il contenitore in un altro che non supporta iteratori ad accesso casuale
Il erase
metodo verrà utilizzato in due modi:
Cancellazione di un singolo elemento:
vector.erase( vector.begin() + 3 ); // Deleting the fourth element
Cancellazione della gamma di elementi:
vector.erase( vector.begin() + 3, vector.begin() + 5 ); // Deleting from fourth element to sixth element
In realtà, la erase
funzione funziona per due profili:
Rimozione di un singolo elemento
iterator erase (iterator position);
Rimozione di una serie di elementi
iterator erase (iterator first, iterator last);
Poiché std :: vec.begin () segna l'inizio del contenitore e se vogliamo eliminare l'elemento ith nel nostro vettore, possiamo usare:
vec.erase(vec.begin() + index);
Se guardi da vicino, vec.begin () è solo un puntatore alla posizione iniziale del nostro vettore e l'aggiunta del valore di i ad esso incrementa il puntatore alla posizione i, quindi invece possiamo accedere al puntatore all'elemento ith da:
&vec[i]
Quindi possiamo scrivere:
vec.erase(&vec[i]); // To delete the ith element
Se hai un vettore non ordinato, puoi trarre vantaggio dal fatto che è non ordinato e utilizzare qualcosa che ho visto da Dan Higgins a CPPCON
template< typename TContainer >
static bool EraseFromUnorderedByIndex( TContainer& inContainer, size_t inIndex )
{
if ( inIndex < inContainer.size() )
{
if ( inIndex != inContainer.size() - 1 )
inContainer[inIndex] = inContainer.back();
inContainer.pop_back();
return true;
}
return false;
}
Poiché l'ordine dell'elenco non ha importanza, basta prendere l'ultimo elemento nell'elenco e copiarlo nella parte superiore dell'elemento che si desidera rimuovere, quindi pop ed eliminare l'ultimo elemento.
iterator + index
ti restituirà effettivamente la posizione dell'iteratore in quell'indice, il che non è vero per tutti i contenitori iterabili. È anche una complessità costante anziché lineare sfruttando il puntatore posteriore.
unordered_remove
e unordered_remove_if
... a meno che non sia stato e me lo sono perso, cosa che sta accadendo sempre più spesso in questi giorni :)
std::remove
riordina il contenitore in modo che tutti gli elementi da rimuovere siano alla fine, non è necessario farlo manualmente in questo modo se si utilizza C ++ 17.
std::remove
aiuta? cppreference afferma che anche in C ++ 17, tutti i remove
sovraccarichi richiedono un predicato e nessuno accetta un indice.
Se lavori con vettori di grandi dimensioni (dimensioni> 100.000) e desideri eliminare molti elementi, ti consiglio di fare qualcosa del genere:
int main(int argc, char** argv) {
vector <int> vec;
vector <int> vec2;
for (int i = 0; i < 20000000; i++){
vec.push_back(i);}
for (int i = 0; i < vec.size(); i++)
{
if(vec.at(i) %3 != 0)
vec2.push_back(i);
}
vec = vec2;
cout << vec.size() << endl;
}
Il codice prende ogni numero in vec che non può essere diviso per 3 e lo copia in vec2. Successivamente copia vec2 in vec. È abbastanza veloce Per elaborare 20.000.000 di elementi, questo algoritmo richiede solo 0,8 secondi!
Ho fatto la stessa cosa con il metodo di cancellazione e ci vuole un sacco di tempo:
Erase-Version (10k elements) : 0.04 sec
Erase-Version (100k elements) : 0.6 sec
Erase-Version (1000k elements): 56 sec
Erase-Version (10000k elements): ...still calculating (>30 min)
Per eliminare un elemento utilizzare il seguente modo:
// declaring and assigning array1
std:vector<int> array1 {0,2,3,4};
// erasing the value in the array
array1.erase(array1.begin()+n);
Per una panoramica più ampia è possibile visitare: http://www.cplusplus.com/reference/vector/vector/erase/
Suggerisco di leggere questo poiché credo che sia quello che stai cercando. https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom
Se usi ad esempio
vec.erase(vec.begin() + 1, vec.begin() + 3);
cancellerai l'ennesimo elemento del vettore ma quando cancellerai il secondo elemento, tutti gli altri elementi del vettore verranno spostati e le dimensioni del vettore saranno -1. Questo può essere un problema se si passa in rassegna il vettore poiché la dimensione del vettore () sta diminuendo. Se hai problemi come questo link fornito suggerito di utilizzare l'algoritmo esistente nella libreria C ++ standard. e "rimuovi" o "rimuovi_if".
Spero che questo abbia aiutato
Le risposte precedenti presuppongono che tu abbia sempre un indice firmato. Purtroppo, std::vector
usa size_type
per l'indicizzazione e difference_type
per l'aritmetica dell'iteratore, quindi non funzionano insieme se hai abilitato "-Conversione" e gli amici. Questo è un altro modo di rispondere alla domanda, pur essendo in grado di gestire sia firmati che non firmati:
Rimuovere:
template<class T, class I, class = typename std::enable_if<std::is_integral<I>::value>::type>
void remove(std::vector<T> &v, I index)
{
const auto &iter = v.cbegin() + gsl::narrow_cast<typename std::vector<T>::difference_type>(index);
v.erase(iter);
}
Prendere:
template<class T, class I, class = typename std::enable_if<std::is_integral<I>::value>::type>
T take(std::vector<T> &v, I index)
{
const auto &iter = v.cbegin() + gsl::narrow_cast<typename std::vector<T>::difference_type>(index);
auto val = *iter;
v.erase(iter);
return val;
}
ecco un altro modo per farlo se vuoi eliminare un elemento trovandolo con il suo valore nel vettore, devi solo farlo sul vettore.
vector<int> ar(n);
ar.erase(remove(ar.begin(), ar.end()), (place your value here from vector array));
rimuoverà il tuo valore da qui. Grazie
il modo più veloce (per i concorsi di programmazione per complessità temporale () = costante)
può cancellare 100M di elemento in 1 secondo;
vector<int> it = (vector<int>::iterator) &vec[pos];
vec.erase(it);
e il modo più leggibile:
vec.erase(vec.begin() + pos);
vector<int>::iterator
non è necessariamente lo stesso diint *