Borrar elementos de un vector

6 minutos de lectura

Borrar elementos de un vector
naveen

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 el vector varias veces o crear una copia más del vector?

Borrar elementos de un vector
Motti

Utilizar el quitar/borrar idioma:

std::vector<int>& vec = myNumbers; // use shorter name
vec.erase(std::remove(vec.begin(), vec.end(), number_in), vec.end());

lo que pasa es que remove compacta los elementos que difieren del valor a eliminar (number_in) al principio de la vector y devuelve el iterador al primer elemento después de ese rango. Luego erase elimina estos elementos (cuyo valor no se especifica).

  • std::remove() desplaza los elementos de forma que se sobrescriben los elementos que se van a eliminar. El algoritmo no cambia el tamaño del contenedor, y si n los elementos se eliminan, entonces no está definido cuáles son los últimos n elementos.

    – Guillermo Tell

    14 de febrero de 2011 a las 15:51

  • la expresión borrar-eliminar se describe en el artículo 32 del libro “STL eficaz: 50 formas específicas de mejorar el uso de la biblioteca de plantillas estándar” de Scott Meyers.

    – Alessandro Jacopson

    1 de junio de 2011 a las 18:47

  • Los ‘modismos’ de STL como este me hacen usar Python para proyectos pequeños.

    – Johannes Overman

    25 de junio de 2013 a las 15:28

  • @LouisDionne que se refiere a la sobrecarga de un iterador, estoy usando la sobrecarga de dos iteradores

    – Motti

    13 de marzo de 2017 a las 7:26

  • @TamaMcGlinn, este código no elimina end() elimina el rango entre begin() y end(). Si begin() es igual a end() hay cero elementos en el rango y no se elimina nada (lo mismo para erase).

    – Motti

    28 de mayo de 2018 a las 6:31

1647579907 745 Borrar elementos de un vector
dalle

Llamar a erase invalidará los iteradores, podría usar:

void erase(std::vector<int>& myNumbers_in, int number_in)
{
    std::vector<int>::iterator iter = myNumbers_in.begin();
    while (iter != myNumbers_in.end())
    {
        if (*iter == number_in)
        {
            iter = myNumbers_in.erase(iter);
        }
        else
        {
           ++iter;
        }
    }

}

O podrías usar estándar::remove_if junto con un funtor y std::vector::erase:

struct Eraser
{
    Eraser(int number_in) : number_in(number_in) {}
    int number_in;
    bool operator()(int i) const
    {
        return i == number_in;
    }
};

std::vector<int> myNumbers;
myNumbers.erase(std::remove_if(myNumbers.begin(), myNumbers.end(), Eraser(number_in)), myNumbers.end());

En lugar de escribir su propio funtor en este caso, podría usar estándar::eliminar:

std::vector<int> myNumbers;
myNumbers.erase(std::remove(myNumbers.begin(), myNumbers.end(), number_in), myNumbers.end());

En C++ 11, podría usar una lambda en lugar de un funtor:

std::vector<int> myNumbers;
myNumbers.erase(std::remove_if(myNumbers.begin(), myNumbers.end(), [number_in](int number){ return number == number_in; }), myNumbers.end());

En C++17 std::experimental::borrar y std::experimental::erase_if también están disponibles, en C ++ 20 estos (finalmente) se renombran a std::borrar y std::erase_if (nota: en Visual Studio 2019, deberá cambiar su versión de lenguaje C++ a la última versión experimental para obtener soporte):

std::vector<int> myNumbers;
std::erase_if(myNumbers, Eraser(number_in)); // or use lambda

o:

std::vector<int> myNumbers;
std::erase(myNumbers, number_in);

  • ¿Por qué usar tu propio functor cuando puedes usar equal_to? :-PAGS sgi.com/tech/stl/equal_to.html

    – Chris Jester-Young

    7 de diciembre de 2008 a las 10:24

  • Por cierto, llamando erase con remove es la forma canónica de hacer esto.

    – Konrad Rodolfo

    7 de diciembre de 2008 a las 10:42

  • Creo que hace exactamente eso. pero debería usar remove_if si usa un funtor propio iirc. o simplemente use eliminar sin el funtor

    – Johannes Schaub – litb

    7 de diciembre de 2008 a las 13:17

  • +1 El código deletreado me ayudó en una competencia de programación, mientras que “simplemente use el idioma eliminar-borrar” no lo hizo.

    usuario529758

    10 de noviembre de 2013 a las 18:42

1647579908 927 Borrar elementos de un vector
sergtk

  1. Puede iterar usando el acceso de índice,

  2. Para evitar la complejidad de O (n ^ 2), puede usar dos índices, i – índice de prueba actual, j – índice para almacenar el siguiente elemento y al final del ciclo, el nuevo tamaño del vector.

código:

void erase(std::vector<int>& v, int num)
{
  size_t j = 0;
  for (size_t i = 0; i < v.size(); ++i) {
    if (v[i] != num) v[j++] = v[i];
  }
  // trim vector to new size
  v.resize(j);
}

En tal caso, no tiene invalidación de iteradores, la complejidad es O (n), y el código es muy conciso y no necesita escribir algunas clases auxiliares, aunque en algunos casos el uso de clases auxiliares puede beneficiar en un código más flexible.

Este código no utiliza 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):

#include <algorithm>

void erase(std::vector<int>& v, int num) {
    vector<int>::iterator it = remove(v.begin(), v.end(), num);
    v.erase(it, v.end());
}

Borrar elementos de un vector
Laserallan

Dependiendo de por qué está haciendo esto, usando un estándar::establecer 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 menor complejidad de tiempo 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 cuántas veces se ha agregado un elemento a su vector o el orden en que se agregaron los elementos.

1647579909 151 Borrar elementos de un vector
Eduard Rostomian

Hay std::erase y std::erase_if ya que C++20 que combina el idioma quitar-borrar.

std::vector<int> nums;
...
std::erase(nums, targetNumber);

o

std::vector<int> nums;
...
std::erase_if(nums, [](int x) { return x % 2 == 0; }); 

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad