Como faço para remover um item de uma stl vector com um determinado valor?

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

  •  09-06-2019
  •  | 
  •  

Pergunta

Eu estava olhando para a documentação da API para stl vector notou que não havia método na classe vector, que permitiu a remoção de um elemento com um determinado valor.Esta parece ser uma operação comum, e parece estranho que não há construída em forma para fazer isso.

Foi útil?

Solução

std::remove na verdade, não apaga o elemento do container, mas ele faz o retorno para o final iterador que pode ser passado para container_type::erase para fazer o REAL de remoção de elementos extra que estão agora no final do recipiente:

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

Outras dicas

Se você deseja remover um item, o seguinte será um pouco mais eficiente.

std::vector<int> v;


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

ou você pode evitar a sobrecarga de mover os itens, se a ordem não importa para você:

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

Use o método global std::remover com begin e end iterador e, em seguida, usar std::vector.apagar realmente remover os elementos.

Links de documentação
std::remover http://www.cppreference.com/cppalgorithm/remove.html
std::vector.apagar 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

Graças a Jim Buck por apontar o meu erro.

Outras respostas tampa de como fazer isso bem, mas eu gostaria de salientar também que ele não é muito estranho que este não é o vetor de API:é ineficiente, pesquisa linear através do vetor para o valor, seguido por uma série de copiar para removê-lo.

Se você está fazendo esta operação de forma intensiva, pode valer a pena considerar std::set em vez disso, por esse motivo.

Se você tiver um vetor não ordenado, em seguida, você pode simplesmente trocar com o último elemento do vetor, em seguida, resize().

Com um ordenado recipiente, você será melhor fora com std::vector::erase().Observe que há uma std::remove() definido no <algorithm>, mas que, na verdade, não fazer o apagar.(Ler com cuidado a documentação).

Uma solução mais curto (que não o força a repetir o nome do vetor 4 vezes) seria usar o 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

Veja também std::remove_if para ser capaz de usar um predicado...

Aqui está o exemplo do link acima:

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

A partir de c++20:

Uma função de membro não apresentou std::erase, que leva o vetor e o valor a ser removidos, como entradas.

ex:

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

Se você quiser fazê-lo sem qualquer extra inclui:

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

Duas formas são não pelo que você pode usar para apagar um item em particular.vamos dar um vetor

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) Não de maneira eficiente : Embora ele parece ser bastante eficiente, mas não é porque a função de eliminação delets os elementos e os turnos de todos os elementos para a esquerda por 1.portanto, a sua complexidade vai 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) forma Eficiente ( RECOMENDADO ) :Ele também é conhecido como APAGAR - para REMOVER idiomas .

  • std::remover transforma o dado intervalo em uma gama com todos os elementos que comparar não é igual a dado elemento deslocado para o início do recipiente.
  • Então, na verdade, não remover a correspondência de elementos.Ele apenas mudou o não correspondido para a partida e dá um iterador para o novo final válido.Ele requer apenas O(n) complexidade.

a saída do algoritmo de remover é :

10 20 30 50 40 50 

como tipo de retorno de remover é iterador para o novo fim do intervalo.

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

Agora use o vetor da função de eliminação para eliminar elementos do novo final para a idade final do vetor.Ele requer O(1) hora.

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

portanto, este método de trabalho em O(n)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top