Quiero borrar un elemento de un vector usando el método de borrado. Pero el problema aquí es que no se garantiza que el elemento ocurra solo una vez en el vector. Puede estar presente varias veces y necesito borrarlas todas. Mi código es algo como esto:
void erase(std::vector<int>& myNumbers_in, int number_in)
{
std::vector<int>::iterator iter = myNumbers_in.begin();
std::vector<int>::iterator endIter = myNumbers_in.end();
for(; iter != endIter; ++iter)
{
if(*iter == number_in)
{
myNumbers_in.erase(iter);
}
}
}
int main(int argc, char* argv[])
{
std::vector<int> myNmbers;
for(int i = 0; i < 2; ++i)
{
myNmbers.push_back(i);
myNmbers.push_back(i);
}
erase(myNmbers, 1);
return 0;
}
Este código obviamente falla porque estoy cambiando el final del vector mientras lo itero. ¿Cuál es la mejor manera de lograr esto? Es decir, ¿hay alguna forma de hacer esto sin iterar a través del vector varias veces o crear una copia más del vector?
std::remove()
desplaza elementos de modo que se sobrescriban los elementos a eliminar. El algoritmo no cambia el tamaño del contenedor, y sin
se eliminan elementos, no está definido cuáles son los últimosn
elementos.Llamar a borrar invalidará los iteradores, puede usar:
O puede usar std :: remove_if junto con un functor y std :: vector :: erase:
En lugar de escribir su propio functor en este caso, podría usar std :: remove :
En C ++ 11, podría usar una lambda en lugar de un functor:
En C ++ 17 std :: experimental :: erase y std :: experimental :: erase_if también están disponibles, en C ++ 20 estos son (finalmente) renombrados a std :: erase y std :: erase_if :
o:
fuente
erase
conremove
es la forma canónica de hacer esto.Puede iterar utilizando el acceso al índice,
Para evitar la complejidad O (n ^ 2), puede utilizar dos índices, i - índice de prueba actual, j - índice para almacenar el siguiente elemento y al final del ciclo un nuevo tamaño del vector.
código:
En tal caso, no puede invalidar los iteradores, la complejidad es O (n) y el código es muy conciso y no es necesario escribir algunas clases auxiliares, aunque en algunos casos el uso de clases auxiliares puede beneficiarse de un código más flexible.
Este código no usa
erase
método, pero resuelve su tarea.Usando stl puro, puede hacer esto de la siguiente manera (esto es similar a la respuesta de Motti):
fuente
Dependiendo de por qué está haciendo esto, usar un std :: set podría ser una mejor idea que std :: vector.
Permite que cada elemento ocurra solo una vez. Si lo agrega varias veces, solo habrá una instancia para borrar de todos modos. Esto hará que la operación de borrado sea trivial. La operación de borrado también tendrá una complejidad de tiempo menor que en el vector, sin embargo, agregar elementos es más lento en el conjunto, por lo que podría no ser una gran ventaja.
Por supuesto, esto no funcionará si está interesado en la cantidad de veces que se agregó un elemento a su vector o el orden en que se agregaron los elementos.
fuente
Para borrar el primer elemento puede utilizar:
fuente