Comment puis-je effacer un élément de std :: vector <> par index?
Question
J'ai un std :: vector
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
vec.erase(???);
La solution
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 plus d'un élément à la fois:
// Deletes the second through third elements (vec[1], vec[2])
vec.erase(vec.begin() + 1, vec.begin() + 3);
Autres conseils
La méthode d'effacement sur std :: vecteur est surchargé, il est donc probablement plus clair appeler
vec.erase(vec.begin() + index);
quand vous voulez seulement effacer un seul élément.
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);
}
La méthode erase
sera utilisée de deux façons:
-
Effacement seul élément:
vector.erase( vector.begin() + 3 ); // Deleting the fourth element
-
plage d'effacement des éléments:
vector.erase( vector.begin() + 3, vector.begin() + 5 ); // Deleting from fourth element to sixth element
Si vous avez un vecteur non ordonnée, vous pouvez profiter du fait qu'il est et non ordonnée utiliser quelque chose que j'ai vu de Dan Higgins à 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;
}
Depuis l'ordre de la liste n'a pas d'importance, il suffit de prendre le dernier élément de la liste et le copier sur le dessus de l'élément que vous voulez supprimer, puis pop et supprimer le dernier élément.
En fait, la fonction erase
travaille pour deux profils:
-
Retrait d'un seul élément
iterator erase (iterator position);
-
Suppression d'un ensemble d'éléments
iterator erase (iterator first, iterator last);
Depuis std :: vec.begin () marque le début du récipient et si l'on veut supprimer l'élément ième dans notre vecteur, nous pouvons utiliser:
vec.erase(vec.begin() + index);
Si vous regardez attentivement, vec.begin () est juste un pointeur vers la position de départ de notre vecteur et en ajoutant la valeur de i à incrémente le pointeur sur la position I, donc au lieu que nous pouvons accéder au pointeur sur l'élément ième par:
&vec[i]
On peut donc écrire:
vec.erase(&vec[i]); // To delete the ith element
Si vous travaillez avec de grands vecteurs (taille> 100 000) et que vous voulez supprimer beaucoup d'éléments, je recommande 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 numéro VEC qui ne peut pas être divisé par 3 et des copies à vec2. Ensuite, il copie vec2 en VEC. Il est assez rapide. Pour traiter 20.000.000 éléments de cet algorithme prend 0,8 sec seulement!
Je l'ai fait la même chose avec l'effacement méthode, et il faut beaucoup, 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 utiliser de la manière 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 plus large aperçu vous pouvez visiter: http://www.cplusplus.com/reference/vector/vector/erase/
Je vous conseille de lire ce que 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 effacez n -ième élément du vecteur, mais quand vous effacez deuxième élément, tous les autres éléments du vecteur sera déplacé et vecteur de taille sera -1. Cela peut être un problème si vous boucle à travers vecteur depuis la taille du vecteur () diminue. Si vous avez un problème comme celui-ci lien fourni suggéré d'utiliser l'algorithme existant dans la bibliothèque standard C ++. et « supprimer » ou « remove_if ».
Espérons que cela a aidé
Les réponses précédentes supposent que vous toujours ont un indice signé. Malheureusement, std::vector
utilise size_type
pour l'indexation, et difference_type
pour l'arithmétique iterator, donc ils ne travaillent pas ensemble si vous avez « -Wconversion » et les amis activés. Ceci est une autre façon de répondre à la question, tout en étant capable de gérer à la fois signé et non signé:
Pour supprimer:
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);
}
Pour 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;
}
ici est une autre façon de le faire si vous voulez supprimer un élément en trouvant cela avec sa valeur dans le vecteur, il vous suffit de le faire sur le vecteur.
vector<int> ar(n);
ar.erase(remove(ar.begin(), ar.end()), (place your value here from vector array));
il va supprimer votre valeur d'ici. merci
Comment cela?
void squeeze(vector<int> &v)
{
int j = 0;
for (int i = 1; i < v.size(); i++)
if (v[i] != v[j] && ++j != i)
v[j] = v[i];
v.resize(j + 1);
}
le moyen le plus rapide (pour les concours de programmation par la complexité temporelle () = constante)
100M peut effacer un objet en 1 seconde;
vector<int> it = (vector<int>::iterator) &vec[pos];
vec.erase(it);
et le plus lisible:
vec.erase(vec.begin() + pos);