Eu tenho um std :: vector <int> e quero excluir o n-ésimo elemento. Como faço isso?
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
vec.erase(???);
Eu tenho um std :: vector <int> e quero excluir o n-ésimo elemento. Como faço isso?
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
vec.erase(???);
Respostas:
Para excluir um único elemento, você pode fazer:
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
// Deletes the second element (vec[1])
vec.erase(vec.begin() + 1);
Ou, para excluir mais de um elemento de uma vez:
// Deletes the second through third elements (vec[1], vec[2])
vec.erase(vec.begin() + 1, vec.begin() + 3);
operator+
é necessariamente definido para iteradores em outros tipos de contêiner, como (você não pode fazer em um , você deve usarlist<T>::iterator
list.begin() + 2
std::list
std::advance
para isso)
std::find_if
O método erase no std :: vector está sobrecarregado, por isso é provavelmente mais claro chamar
vec.erase(vec.begin() + index);
quando você deseja apagar apenas um único elemento.
vec.begin()
qual é válido.
vec.erase(0)
não funciona, mas vec.erase(vec.begin()+0)
(ou sem +0) funciona. Caso contrário, eu não obter chamada de função correspondente, que é por isso que vim aqui
vec.erase(0)
pode realmente compilar se 0
passa a ser interpretada como a constante ponteiro nulo ...
template <typename T>
void remove(std::vector<T>& vec, size_t pos)
{
std::vector<T>::iterator it = vec.begin();
std::advance(it, pos);
vec.erase(it);
}
template <typename T> void remove(std::vector<T>& vec, size_t pos) { vec.erase(vec.begin + pos); }
eu não estou dizendo que qualquer uma é melhor, apenas pedindo por interesse pessoal e retornar o melhor resultado que essa pergunta poderia obter.
vector<T>::iterator
é um iterador de acesso aleatório, sua versão é boa e talvez um pouco mais clara. Mas a versão que Max postou deve funcionar muito bem se você alterar o recipiente para um outro que não suporta iteradores de acesso aleatório
O erase
método será usado de duas maneiras:
Apagando um único elemento:
vector.erase( vector.begin() + 3 ); // Deleting the fourth element
Apagando vários elementos:
vector.erase( vector.begin() + 3, vector.begin() + 5 ); // Deleting from fourth element to sixth element
Na verdade, a erase
função funciona para dois perfis:
Removendo um Único Elemento
iterator erase (iterator position);
Removendo uma variedade de elementos
iterator erase (iterator first, iterator last);
Como std :: vec.begin () marca o início do contêiner e, se quisermos excluir o i-ésimo elemento em nosso vetor, podemos usar:
vec.erase(vec.begin() + index);
Se você observar atentamente, vec.begin () é apenas um ponteiro para a posição inicial do nosso vetor e, ao adicionar o valor de i, ele aumenta o ponteiro para a posição i; portanto, podemos acessar o ponteiro para o i-ésimo elemento:
&vec[i]
Para que possamos escrever:
vec.erase(&vec[i]); // To delete the ith element
Se você tem um vetor não ordenado, pode aproveitar o fato de ele não ser ordenado e usar algo que vi de Dan Higgins no CPPCON
template< typename TContainer >
static bool EraseFromUnorderedByIndex( TContainer& inContainer, size_t inIndex )
{
if ( inIndex < inContainer.size() )
{
if ( inIndex != inContainer.size() - 1 )
inContainer[inIndex] = inContainer.back();
inContainer.pop_back();
return true;
}
return false;
}
Como a ordem da lista não importa, basta pegar o último elemento da lista e copiá-lo por cima do item que você deseja remover, em seguida, pop e exclua o último item.
iterator + index
você retornará a posição do iterador nesse índice, o que não é verdade para todos os contêineres iteráveis. Também é uma complexidade constante, em vez de linear, aproveitando o ponteiro de trás.
unordered_remove
e unordered_remove_if
… a menos que tenha sido e eu perdi, o que está acontecendo com mais frequência hoje em dia :)
std::remove
reordena o contêiner para que todos os elementos a serem removidos estejam no final, não é necessário fazê-lo manualmente dessa maneira, se você estiver usando o C ++ 17.
std::remove
ajuda? A cppreference afirma que, mesmo no C ++ 17, todas as remove
sobrecargas exigem um predicado e nenhuma recebe um índice.
Se você trabalha com vetores grandes (tamanho> 100.000) e deseja excluir muitos elementos, eu recomendaria fazer algo assim:
int main(int argc, char** argv) {
vector <int> vec;
vector <int> vec2;
for (int i = 0; i < 20000000; i++){
vec.push_back(i);}
for (int i = 0; i < vec.size(); i++)
{
if(vec.at(i) %3 != 0)
vec2.push_back(i);
}
vec = vec2;
cout << vec.size() << endl;
}
O código pega todos os números no vec que não podem ser divididos por 3 e o copia no vec2. Depois, copia o vec2 no vec. É bem rápido. Para processar 20.000.000 de elementos, esse algoritmo leva apenas 0,8 s!
Fiz a mesma coisa com o método erase, e leva muito e muito tempo:
Erase-Version (10k elements) : 0.04 sec
Erase-Version (100k elements) : 0.6 sec
Erase-Version (1000k elements): 56 sec
Erase-Version (10000k elements): ...still calculating (>30 min)
Para excluir um elemento, use o seguinte caminho:
// declaring and assigning array1
std:vector<int> array1 {0,2,3,4};
// erasing the value in the array
array1.erase(array1.begin()+n);
Para uma visão mais ampla visite: http://www.cplusplus.com/reference/vector/vector/erase/
Sugiro ler isso, pois acredito que é isso que você está procurando.https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom
Se você usa por exemplo
vec.erase(vec.begin() + 1, vec.begin() + 3);
você apagará o n-ésimo elemento do vetor, mas quando você apagar o segundo elemento, todos os outros elementos do vetor serão deslocados e o tamanho do vetor será -1. Isso pode ser um problema se você percorrer o vetor, pois o tamanho do vetor () está diminuindo. Se você tiver um problema como este, o link fornecido sugere o uso do algoritmo existente na biblioteca C ++ padrão. e "remover" ou "remover_se".
Espero que isso tenha ajudado
As respostas anteriores assumem que você sempre tem um índice assinado. Infelizmente, std::vector
usa size_type
para indexação e difference_type
aritmética do iterador, para que não funcionem juntos se você tiver "-Wconversion" e amigos ativados. Esta é outra maneira de responder à pergunta, enquanto é capaz de lidar com assinados e não assinados:
Remover:
template<class T, class I, class = typename std::enable_if<std::is_integral<I>::value>::type>
void remove(std::vector<T> &v, I index)
{
const auto &iter = v.cbegin() + gsl::narrow_cast<typename std::vector<T>::difference_type>(index);
v.erase(iter);
}
Pegar:
template<class T, class I, class = typename std::enable_if<std::is_integral<I>::value>::type>
T take(std::vector<T> &v, I index)
{
const auto &iter = v.cbegin() + gsl::narrow_cast<typename std::vector<T>::difference_type>(index);
auto val = *iter;
v.erase(iter);
return val;
}
aqui está mais uma maneira de fazer isso, se você deseja excluir um elemento encontrando-o com seu valor em vetor, basta fazer isso em vetor.
vector<int> ar(n);
ar.erase(remove(ar.begin(), ar.end()), (place your value here from vector array));
isso removerá seu valor daqui. obrigado
o caminho mais rápido (para programação de concursos por complexidade de tempo () = constante)
pode apagar 100 milhões de itens em 1 segundo;
vector<int> it = (vector<int>::iterator) &vec[pos];
vec.erase(it);
e maneira mais legível:
vec.erase(vec.begin() + pos);
vector<int>::iterator
não é necessariamente o mesmo queint *