web-dev-qa-db-fra.com

Comment puis-je effacer un élément de std :: vector <> par index?

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(???);
410
dau_man

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);
570
mmmmmmmm

La méthode erase sur std :: vector est surchargée, il est donc probablement plus clair d'appeler

vec.erase(vec.begin() + index);

lorsque vous ne voulez effacer qu'un seul élément.

182
CodeBuddy
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);
}
49
Max

La méthode erase sera utilisée de deux manières:

  1. Effacer un seul élément:

    vector.erase( vector.begin() + 3 ); // Deleting the fourth element
    
  2. Effacement de la gamme d'éléments:

    vector.erase( vector.begin() + 3, vector.begin() + 5 ); // Deleting from fourth element to sixth element
    
14
Eswaran Pandi

En fait, la fonction erase fonctionne pour deux profils:

  • Enlever un seul élément

    iterator erase (iterator position);
    
  • Supprimer une série d'éléments

    iterator erase (iterator first, iterator last);
    

Puisque std :: vec.begin () marque le début du conteneur et si nous voulons supprimer l’it élément de notre vecteur, nous pouvons utiliser:

vec.erase(vec.begin() + index);

Si vous regardez de plus près, vec.begin () est juste un pointeur sur la position de départ de notre vecteur et y ajouter la valeur de i incrémente le pointeur sur i position. Nous pouvons donc accéder au pointeur sur le ième élément de la manière suivante:

&vec[i]

Pour que nous puissions écrire:

vec.erase(&vec[i]); // To delete the ith element
6
Varun Garg

Si vous avez un vecteur non ordonné, vous pouvez tirer parti du fait qu'il est non ordonné et 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;
}

Étant donné que l'ordre de la liste n'a pas d'importance, prenez simplement le dernier élément de la liste et copiez-le au-dessus de l'élément que vous souhaitez supprimer, puis affichez et supprimez le dernier élément.

6
Clay J

Si vous travaillez avec des vecteurs volumineux (taille> 100 000) et souhaitez supprimer de nombreux éléments, je vous recommande de procéder de la manière suivante:

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 d'éléments, cet algorithme ne prend que 0,8 seconde!

J'ai fait la même chose avec la méthode erase, 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)
4
Fabian

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 un aperçu plus général, vous pouvez visiter: http://www.cplusplus.com/reference/vector/vector/erase/

2
cammando

Je suggère de lire ceci car je crois que c’est ce que vous cherchez . 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 n-iè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 de -1. Cela peut poser problème si vous parcourez un vecteur, car sa taille () diminue. Si vous avez un problème comme celui-ci, le lien proposé vous suggère d'utiliser l'algorithme existant dans la bibliothèque standard C++. et "remove" ou "remove_if".

J'espère que cela a aidé

1
explorer

Que dis-tu de ça?

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);
}
0
def

voici un autre moyen de le faire si vous voulez supprimer un élément en le trouvant avec sa valeur dans vecteur, il vous suffit de le faire sur 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

0
meenachinmay

Les réponses précédentes supposent que vous ayez toujours un index signé. Malheureusement, std::vector utilise size_type pour l'indexation et difference_type pour l'arithmétique des itérateurs, de sorte qu'ils ne fonctionnent pas ensemble si "-Wconversion" et vos 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é:

Retirer:

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;
}
0
Rian Quinn

le moyen le plus rapide (pour programmer des concours par complexité temporelle () = constant)

peut effacer 100M article en 1 seconde;

    vector<int> it = (vector<int>::iterator) &vec[pos];
    vec.erase(it);

et le plus lisible: vec.erase(vec.begin() + pos);

0
R.hatam