¿Cómo elimino un elemento de un vector stl con un valor determinado?

StackOverflow https://stackoverflow.com/questions/39912

  •  09-06-2019
  •  | 
  •  

Pregunta

Estaba mirando la documentación de la API para el vector stl y noté que no había ningún método en la clase de vector que permitiera la eliminación de un elemento con un valor determinado.Esto parece una operación común y parece extraño que no exista una forma integrada de hacerlo.

¿Fue útil?

Solución

std::remove en realidad no borra el elemento del contenedor, pero devuelve el nuevo iterador final que se puede pasar a container_type::erase para hacer la eliminación REAL de los elementos extra que ahora están al final del contenedor:

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

Otros consejos

Si quieres eliminar un elemento, lo siguiente será un poco más eficiente.

std::vector<int> v;


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

o puede evitar los gastos generales de mover los artículos si el orden no le importa:

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

Utilice el método global std::remove con el iterador inicial y final, y luego utilice std::vector.erase para eliminar los elementos.

Enlaces de documentación
std::eliminar http://www.cppreference.com/cppalgorithm/remove.html
std::vector.erase http://www.cppreference.com/cppvector/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

Gracias a Jim Buck por señalar mi error.

Las otras respuestas cubren cómo hacer esto bien, pero también pensé en señalar que no es realmente extraño que esto no esté en la API vectorial:Es una búsqueda lineal ineficiente a través del vector del valor, seguida de un montón de copias para eliminarlo.

Si está realizando esta operación de forma intensiva, puede valer la pena considerar std::set por este motivo.

Si tiene un vector sin ordenar, simplemente puede intercambiarlo con el último elemento del vector y luego resize().

Con un contenedor ordenado, lo mejor será ‍ std::vector::erase().Tenga en cuenta que hay un std::remove() definido en <algorithm>, pero eso en realidad no borra.(Lea atentamente la documentación).

Una solución más corta (que no te obliga a repetir el nombre del vector 4 veces) sería usar Boost:

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

// ...

boost::remove_erase(vec, int_to_remove);

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

Ver también std::remove_if para poder utilizar un predicado...

Aquí está el ejemplo del enlace de arriba:

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

De c++20:

Se introdujo una función no miembro std::erase, que toma el vector y el valor que se eliminarán como entradas.

ex:

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

Si quieres hacerlo sin ningún extra incluye:

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

Existen dos formas que puede utilizar para borrar un elemento en particular.tomemos un vector

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) Manera no eficiente: Aunque parece ser bastante eficiente, no lo es porque la función de borrado elimina los elementos y los desplaza 1 hacia la izquierda.entonces su complejidad será 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) Manera eficiente (RECOMENDADA) :También se le conoce como BORRAR - ELIMINAR modismos .

  • std::remove transforma el rango dado en un rango con todos los elementos que no se comparan con el elemento dado desplazados al inicio del contenedor.
  • Por lo tanto, en realidad no elimine los elementos coincidentes.Simplemente cambió el no coincidente al inicio y le da un iterador al nuevo final válido.Solo requiere complejidad O(n).

La salida del algoritmo de eliminación es:

10 20 30 50 40 50 

como tipo de retorno de eliminación es un iterador hasta el nuevo final de ese rango.

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

Ahora use la función de borrado del vector para eliminar elementos desde el extremo nuevo hasta el extremo anterior del vector.Requiere tiempo O (1).

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

entonces este método funciona en O(n)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top