Comment supprimer un élément d'un vecteur stl avec une certaine valeur ?

StackOverflow https://stackoverflow.com/questions/39912

  •  09-06-2019
  •  | 
  •  

Question

Je regardais la documentation de l'API pour stl vector et j'ai remarqué qu'il n'y avait aucune méthode sur la classe vector permettant la suppression d'un élément avec une certaine valeur.Cela semble être une opération courante, et il semble étrange qu'il n'y ait aucun moyen intégré pour le faire.

Était-ce utile?

La solution

std::remove n'efface pas réellement l'élément du conteneur, mais renvoie le nouvel itérateur de fin qui peut être transmis à container_type::erase pour faire la VRAIE suppression des éléments supplémentaires qui se trouvent maintenant à la fin du conteneur :

std::vector<int> vec;
// .. put in some values ..
int int_to_remove = n;
vec.erase(std::remove(vec.begin(), vec.end(), int_to_remove), vec.end());

Autres conseils

Si vous souhaitez supprimer un article, ce qui suit sera un peu plus efficace.

std::vector<int> v;


auto it = std::find(v.begin(), v.end(), 5);
if(it != v.end())
    v.erase(it);

ou vous pouvez éviter les frais généraux liés au déplacement des articles si la commande ne vous importe pas :

std::vector<int> v;

auto it = std::find(v.begin(), v.end(), 5);

if (it != v.end()) {
  using std::swap;

  // swap the one to be removed with the last element
  // and remove the item at the end of the container
  // to prevent moving all items after '5' by one
  swap(*it, v.back());
  v.pop_back();
}

Utilisez la méthode globale std::remove avec les itérateurs de début et de fin, puis utilisez std::vector.erase pour supprimer réellement les éléments.

Liens vers la documentation
std :: supprimer http://www.cppreference.com/cppalgorithm/remove.html
std :: vecteur.effacer http://www.cppreference.com/cppvector/erase.html

std::vector<int> v;
v.push_back(1);
v.push_back(2);

//Vector should contain the elements 1, 2

//Find new end iterator
std::vector<int>::iterator newEnd = std::remove(v.begin(), v.end(), 1);

//Erase the "removed" elements.
v.erase(newEnd, v.end());

//Vector should now only contain 2

Merci à Jim Buck d'avoir signalé mon erreur.

Les autres réponses expliquent comment bien faire cela, mais j'ai pensé souligner également qu'il n'est pas vraiment étrange que cela ne soit pas dans l'API vectorielle :il s'agit d'une recherche linéaire et inefficace de la valeur dans le vecteur, suivie d'un tas de copies pour la supprimer.

Si vous effectuez cette opération de manière intensive, cela peut valoir la peine d'envisager plutôt std::set pour cette raison.

Si vous avez un vecteur non trié, vous pouvez simplement échanger avec le dernier élément vectoriel, puis resize().

Avec un conteneur commandé, vous serez mieux loti avec ‍ std::vector::erase().Notez qu'il existe un std::remove() défini dans <algorithm>, mais cela ne fait pas réellement l'effacement.(Lisez attentivement la documentation).

Une solution plus courte (qui ne vous oblige pas à répéter 4 fois le nom du vecteur) serait d'utiliser Boost :

#include <boost/range/algorithm_ext/erase.hpp>

// ...

boost::remove_erase(vec, int_to_remove);

Voir http://www.boost.org/doc/libs/1_64_0/libs/range/doc/html/range/reference/algorithms/new/remove_erase.html

Voir également std ::remove_if pouvoir utiliser un prédicat...

Voici l'exemple du lien ci-dessus :

vector<int> V;
V.push_back(1);
V.push_back(4);
V.push_back(2);
V.push_back(8);
V.push_back(5);
V.push_back(7);

copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
    // The output is "1 4 2 8 5 7"

vector<int>::iterator new_end = 
    remove_if(V.begin(), V.end(), 
              compose1(bind2nd(equal_to<int>(), 0),
                       bind2nd(modulus<int>(), 2)));
V.erase(new_end, V.end()); [1]

copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
    // The output is "1 5 7".

Depuis c++20:

Une fonction non membre introduite std::erase, qui prend le vecteur et la valeur à supprimer comme entrées.

ex:

std::vector<int> v = {90,80,70,60,50};
std::erase(v,50);

Si vous voulez le faire sans aucun supplément, cela inclut :

vector<IComponent*> myComponents; //assume it has items in it already.
void RemoveComponent(IComponent* componentToRemove)
{
    IComponent* juggler;

    if (componentToRemove != NULL)
    {
        for (int currComponentIndex = 0; currComponentIndex < myComponents.size(); currComponentIndex++)
        {
            if (componentToRemove == myComponents[currComponentIndex])
            {
                //Since we don't care about order, swap with the last element, then delete it.
                juggler = myComponents[currComponentIndex];
                myComponents[currComponentIndex] = myComponents[myComponents.size() - 1];
                myComponents[myComponents.size() - 1] = juggler;

                //Remove it from memory and let the vector know too.
                myComponents.pop_back();
                delete juggler;
            }
        }
    }
}

Il existe deux méthodes que vous pouvez utiliser pour effacer un élément en particulier.prenons un vecteur

std :: vector < int > v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(40);
v.push_back(50);

1) Manière non efficace : Bien que cela semble assez efficace, ce n'est pas le cas parce que la fonction d'effacement supprime les éléments et décale tous les éléments vers la gauche de 1.donc sa complexité sera O(n^2)

std :: vector < int > :: iterator itr = v.begin();
int value = 40;
while ( itr != v.end() )
{
   if(*itr == value)
   { 
      v.erase(itr);
   }
   else
       ++itr;
}

2) Manière efficace (RECOMMANDÉE) :Il est également connu sous le nom EFFACER - SUPPRIMER les expressions idiomatiques .

  • std::remove transforme la plage donnée en une plage avec tous les éléments qui ne sont pas égaux à l'élément donné décalés au début du conteneur.
  • Donc, ne supprimez pas les éléments correspondants.Il vient de déplacer le non correspondant au début et donne un itérateur à une nouvelle fin valide.Cela nécessite juste une complexité O(n).

le résultat de l'algorithme de suppression est :

10 20 30 50 40 50 

comme type de retour de suppression, il s'agit d'un itérateur vers la nouvelle fin de cette plage.

template <class ForwardIterator, class T>
  ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val);

Utilisez maintenant la fonction d'effacement du vecteur pour supprimer des éléments de la nouvelle extrémité à l'ancienne extrémité du vecteur.Cela nécessite un temps O(1).

v.erase ( std :: remove (v.begin() , v.end() , element ) , v.end () );

donc cette méthode fonctionne en O(n)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top