J'ai un std :: vector <int>, et je veux supprimer le nième élément. Comment je fais ça?
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
vec.erase(???);
J'ai un std :: vector <int>, et je veux supprimer le nième élément. Comment je fais ça?
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
vec.erase(???);
Réponses:
Pour supprimer un seul élément, vous pouvez faire:
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, pour supprimer plusieurs éléments à la fois:
// Deletes the second through third elements (vec[1], vec[2])
vec.erase(vec.begin() + 1, vec.begin() + 3);
operator+
n'est pas nécessairement défini pour les itérateurs sur d'autres types de conteneurs, comme list<T>::iterator
(vous ne pouvez pas le faire list.begin() + 2
sur un std::list
, vous devez l'utiliser std::advance
pour cela)
std::find_if
La méthode d'effacement sur std :: vector est surchargée, il est donc probablement plus clair d'appeler
vec.erase(vec.begin() + index);
lorsque vous ne souhaitez effacer qu'un seul élément.
vec.begin()
ce qui est valide.
vec.erase(0)
cela ne fonctionne pas, mais vec.erase(vec.begin()+0)
(ou sans +0) le fait. Sinon, je ne reçois aucun appel de fonction correspondant, c'est pourquoi je suis venu ici
vec.erase(0)
peut en fait se compiler s'il 0
arrive d'être interprété comme la constante du pointeur nul ...
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); }
je ne dis pas que c'est mieux, simplement en demandant par intérêt personnel et en retournant le meilleur résultat que cette question pourrait obtenir.
vector<T>::iterator
est un itérateur à accès aléatoire, votre version est correcte et peut-être un peu plus claire. Mais la version publiée par Max devrait fonctionner très bien si vous changez le conteneur en un autre qui ne prend pas en charge les itérateurs à accès aléatoire
La erase
méthode sera utilisée de deux manières:
Effacement d'un seul élément:
vector.erase( vector.begin() + 3 ); // Deleting the fourth element
Effacement d'une gamme d'éléments:
vector.erase( vector.begin() + 3, vector.begin() + 5 ); // Deleting from fourth element to sixth element
En fait, la erase
fonction fonctionne pour deux profils:
Suppression d'un seul élément
iterator erase (iterator position);
Suppression d'une gamme d'éléments
iterator erase (iterator first, iterator last);
Puisque std :: vec.begin () marque le début du conteneur et si nous voulons supprimer le ième élément de notre vecteur, nous pouvons utiliser:
vec.erase(vec.begin() + index);
Si vous regardez attentivement, vec.begin () n'est qu'un pointeur vers la position de départ de notre vecteur et l'ajout de la valeur de i augmente le pointeur à la position i, nous pouvons donc accéder au pointeur vers le ième élément en:
&vec[i]
On peut donc écrire:
vec.erase(&vec[i]); // To delete the ith element
Si vous avez un vecteur non ordonné, vous pouvez profiter du fait qu'il n'est pas ordonné et utiliser quelque chose que j'ai vu de Dan Higgins au 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;
}
Étant donné que l'ordre des listes n'a pas d'importance, prenez simplement le dernier élément de la liste et copiez-le par-dessus l'élément que vous souhaitez supprimer, puis sautez et supprimez le dernier élément.
iterator + index
vous donnera en fait la position de l'itérateur à cet index, ce qui n'est pas le cas de tous les conteneurs itérables. C'est également une complexité constante au lieu d'être linéaire en tirant parti du pointeur arrière.
unordered_remove
et à mesure unordered_remove_if
que cela n'a pas été le cas et que je l'ai manqué, ce qui se produit de plus en plus ces jours-ci :)
std::remove
réorganise le conteneur pour que tous les éléments à supprimer soient à la fin, pas besoin de le faire manuellement comme ceci si vous utilisez C ++ 17.
std::remove
aide? cppreference affirme que même en C ++ 17, toutes les remove
surcharges nécessitent un prédicat et aucune ne prend d'index.
Si vous travaillez avec de grands vecteurs (taille> 100 000) et que vous souhaitez supprimer de nombreux éléments, je recommanderais de faire quelque chose comme ceci:
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;
}
Le code prend chaque nombre dans vec qui ne peut pas être divisé par 3 et le copie dans vec2. Ensuite, il copie vec2 dans vec. C'est assez rapide. Pour traiter 20 000 000 éléments, cet algorithme ne prend que 0,8 s!
J'ai fait la même chose avec la méthode d'effacement, et cela prend beaucoup de temps:
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)
Pour supprimer un élément, utilisez la méthode suivante:
// declaring and assigning array1
std:vector<int> array1 {0,2,3,4};
// erasing the value in the array
array1.erase(array1.begin()+n);
Pour une vue d' ensemble plus large, vous pouvez visiter: http://www.cplusplus.com/reference/vector/vector/erase/
Je suggère de lire ceci car je crois que c'est ce que vous recherchez.https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom
Si vous utilisez par exemple
vec.erase(vec.begin() + 1, vec.begin() + 3);
vous effacerez le nième élément du vecteur mais lorsque vous effacerez le deuxième élément, tous les autres éléments du vecteur seront décalés et la taille du vecteur sera -1. Cela peut être un problème si vous parcourez le vecteur car la taille du vecteur () diminue. Si vous avez un problème comme celui-ci, le lien proposé suggère d'utiliser l'algorithme existant dans la bibliothèque C ++ standard. et "supprimer" ou "supprimer_si".
J'espère que cela a aidé
Les réponses précédentes supposent que vous avez toujours un index signé. Malheureusement, les std::vector
utilisations size_type
pour l'indexation, etdifference_type
pour l'arithmétique des itérateurs, donc ils ne fonctionnent pas ensemble si "-Wconversion" et amis sont activés. C'est une autre façon de répondre à la question, tout en étant capable de gérer à la fois signé et non signé:
Ôter:
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);
}
Prendre:
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;
}
voici une autre façon de le faire si vous voulez supprimer un élément en le trouvant avec sa valeur dans vector, il vous suffit de le faire sur vector.
vector<int> ar(n);
ar.erase(remove(ar.begin(), ar.end()), (place your value here from vector array));
cela supprimera votre valeur d'ici. Merci
le moyen le plus rapide (pour programmer des concours par complexité temporelle () = constante)
peut effacer 100M d'élément en 1 seconde;
vector<int> it = (vector<int>::iterator) &vec[pos];
vec.erase(it);
et le plus lisible:
vec.erase(vec.begin() + pos);
vector<int>::iterator
n'est pas nécessairement le même queint *