Tengo un std :: vector <int>, y quiero eliminar el enésimo elemento. ¿Cómo puedo hacer eso?
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
vec.erase(???);
Tengo un std :: vector <int>, y quiero eliminar el enésimo elemento. ¿Cómo puedo hacer eso?
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
vec.erase(???);
Respuestas:
Para eliminar un solo elemento, puede hacer:
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);
O, para eliminar más de un elemento a la vez:
// Deletes the second through third elements (vec[1], vec[2])
vec.erase(vec.begin() + 1, vec.begin() + 3);
operator+
está necesariamente definido para iteradores en otros tipos de contenedores, como (no puede hacerlo en un , debe usar para eso)list<T>::iterator
list.begin() + 2
std::list
std::advance
std::find_if
El método de borrado en std :: vector está sobrecargado, por lo que probablemente sea más claro llamar
vec.erase(vec.begin() + index);
cuando solo quieres borrar un solo elemento.
vec.begin()
cuál es válido.
vec.erase(0)
no funciona, pero vec.erase(vec.begin()+0)
(o sin +0) sí. De lo contrario, no recibo una llamada de función coincidente, por eso vine aquí
vec.erase(0)
realidad puede compilarse si 0
se interpreta como la constante de puntero nulo ...
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); }
No estoy diciendo que ninguno sea mejor, simplemente preguntando por interés personal y para devolver el mejor resultado que esta pregunta podría obtener.
vector<T>::iterator
es un iterador de acceso aleatorio, su versión está bien y quizás un poco más clara. Pero la versión que publicó Max debería funcionar bien si cambia el contenedor a otro que no sea compatible con iteradores de acceso aleatorio
El erase
método se usará de dos maneras:
Borrar un solo elemento:
vector.erase( vector.begin() + 3 ); // Deleting the fourth element
Borrado de rango de elementos:
vector.erase( vector.begin() + 3, vector.begin() + 5 ); // Deleting from fourth element to sixth element
En realidad, la erase
función funciona para dos perfiles:
Eliminar un solo elemento
iterator erase (iterator position);
Eliminar una gama de elementos
iterator erase (iterator first, iterator last);
Dado que std :: vec.begin () marca el inicio del contenedor y si queremos eliminar el elemento i-ésimo en nuestro vector, podemos usar:
vec.erase(vec.begin() + index);
Si observa de cerca, vec.begin () es solo un puntero a la posición inicial de nuestro vector y al agregarle el valor de i incrementa el puntero a la posición i, por lo que podemos acceder al puntero al elemento i-ésimo de la siguiente manera:
&vec[i]
Entonces podemos escribir:
vec.erase(&vec[i]); // To delete the ith element
Si tiene un vector desordenado, puede aprovechar el hecho de que está desordenado y usar algo que vi de Dan Higgins en 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;
}
Como el orden de la lista no importa, solo tome el último elemento de la lista y cópielo sobre la parte superior del elemento que desea eliminar, luego haga estallar y elimine el último elemento.
iterator + index
realmente le devolverá la posición del iterador en ese índice, lo que no es cierto para todos los contenedores iterables. También es una complejidad constante en lugar de lineal al aprovechar el puntero posterior.
unordered_remove
y unordered_remove_if
... a menos que lo haya sido y lo haya extrañado, lo que sucede cada vez más a menudo en estos días :)
std::remove
reordena el contenedor para que todos los elementos que se eliminarán estén al final, no es necesario hacerlo manualmente si está usando C ++ 17.
std::remove
ayuda? cppreference afirma que incluso en C ++ 17, todas las remove
sobrecargas requieren un predicado y ninguna toma un índice.
Si trabaja con vectores grandes (tamaño> 100,000) y desea eliminar muchos elementos, le recomendaría hacer algo como esto:
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;
}
El código toma cada número en vec que no se puede dividir entre 3 y lo copia en vec2. Luego copia vec2 en vec. Es bastante rápido ¡Para procesar 20,000,000 elementos, este algoritmo solo toma 0.8 segundos!
Hice lo mismo con el método de borrado, y lleva mucho, mucho tiempo:
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)
Para eliminar un elemento, use la siguiente manera:
// declaring and assigning array1
std:vector<int> array1 {0,2,3,4};
// erasing the value in the array
array1.erase(array1.begin()+n);
Para obtener una descripción más amplia , puede visitar: http://www.cplusplus.com/reference/vector/vector/erase/
Sugiero leer esto ya que creo que eso es lo que estás buscando. https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom
Si usas por ejemplo
vec.erase(vec.begin() + 1, vec.begin() + 3);
borrará el enésimo elemento del vector, pero cuando borre el segundo elemento, todos los demás elementos del vector se desplazarán y el tamaño del vector será -1. Esto puede ser un problema si recorre el vector ya que el tamaño del vector () está disminuyendo. Si tiene un problema como este, el enlace proporcionado sugiere utilizar el algoritmo existente en la biblioteca estándar de C ++. y "eliminar" o "eliminar_si".
Espero que esto haya ayudado
Las respuestas anteriores suponen que siempre tiene un índice firmado. Lamentablemente, los std::vector
usos size_type
para la indexación, ydifference_type
aritmética de iteradores, por lo que no funcionan juntos si tiene "-Wconversion" y amigos habilitados. Esta es otra forma de responder la pregunta, al tiempo que puede manejar tanto con signo como sin signo:
Para eliminar:
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);
}
Tomar:
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;
}
Aquí hay una forma más de hacer esto si desea eliminar un elemento encontrando esto con su valor en vector, solo necesita hacer esto en vector.
vector<int> ar(n);
ar.erase(remove(ar.begin(), ar.end()), (place your value here from vector array));
eliminará tu valor de aquí. Gracias
la forma más rápida (para programar concursos por complejidad de tiempo () = constante)
puede borrar un elemento de 100M en 1 segundo;
vector<int> it = (vector<int>::iterator) &vec[pos];
vec.erase(it);
y la forma más legible:
vec.erase(vec.begin() + pos);
vector<int>::iterator
no es necesariamente lo mismo queint *