Quero limpar um elemento de um vetor usando o método erase. Mas o problema aqui é que não é garantido que o elemento ocorra apenas uma vez no vetor. Pode estar presente várias vezes e preciso limpar todos eles. Meu código é mais ou menos assim:
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;
}
Esse código obviamente falha porque estou alterando o final do vetor enquanto itero por ele. Qual a melhor maneira de alcançar isto? Ou seja, há alguma maneira de fazer isso sem iterar o vetor várias vezes ou criar mais uma cópia do vetor?
std::remove()
desloca elementos de forma que os elementos a serem removidos sejam sobrescritos. O algoritmo não muda o tamanho do container, e se osn
elementos são removidos então fica indefinido quais são os últimosn
elementos.Chamar o apagamento invalidará os iteradores, você pode usar:
Ou você pode usar std :: remove_if junto com um functor e std :: vector :: erase:
Em vez de escrever seu próprio functor, neste caso, você pode usar std :: remove :
No C ++ 11, você pode usar um lambda em vez de um functor:
Em C ++ 17 std :: experimental :: erase e std :: experimental :: erase_if também estão disponíveis, em C ++ 20 eles são (finalmente) renomeados para std :: erase e std :: erase_if :
ou:
fonte
erase
comremove
é a maneira canônica de fazer isso.Você pode iterar usando o acesso ao índice,
Para evitar a complexidade O (n ^ 2), você pode usar dois índices, i - índice de teste atual, j - índice para armazenar o próximo item e no final do ciclo um novo tamanho do vetor.
código:
Nesse caso, você não tem invalidação de iteradores, a complexidade é O (n) e o código é muito conciso e você não precisa escrever algumas classes auxiliares, embora em alguns casos o uso de classes auxiliares possa se beneficiar com um código mais flexível.
Este código não usa
erase
método, mas resolve sua tarefa.Usando STL puro, você pode fazer isso da seguinte maneira (isso é semelhante à resposta do Motti):
fonte
Dependendo de porque você está fazendo isso, usar um std :: set pode ser uma ideia melhor do que std :: vector.
Ele permite que cada elemento ocorra apenas uma vez. Se você adicioná-lo várias vezes, haverá apenas uma instância para apagar de qualquer maneira. Isso tornará a operação de apagamento trivial. A operação de apagamento também terá menor complexidade de tempo do que no vetor; no entanto, adicionar elementos é mais lento no conjunto, portanto, pode não ser uma grande vantagem.
É claro que isso não funcionará se você estiver interessado em quantas vezes um elemento foi adicionado ao seu vetor ou a ordem em que os elementos foram adicionados.
fonte
Para apagar o primeiro elemento, você pode usar:
fonte