Comment vérifier qu’un élément est dans un std :: set?

Comment vérifiez-vous qu’un élément est dans un ensemble?

Existe-t-il un équivalent plus simple du code suivant:

myset.find(x) != myset.end() 

La manière typique de vérifier l’existence dans de nombreux conteneurs STL est la suivante:

 const bool is_in = container.find(element) != container.end(); 

Une autre façon de dire simplement si un élément existe est de vérifier le count()

 if (myset.count(x)) { // x is in the set, count is 1 } else { // count zero, ie x not in the set } 

La plupart du temps, cependant, je me trouve obligé d’accéder à l’élément chaque fois que je vérifie son existence.

Il faudrait donc que je trouve l’iterator de toute façon. Alors, bien sûr, il vaut mieux le comparer à la end .

 set< X >::iterator it = myset.find(x); if (it != myset.end()) { // do something with *it } 

Juste pour clarifier, la raison pour laquelle il n’y a pas de membre comme contains() dans ces types de conteneur est que cela vous ouvrirait à écrire du code inefficace. Une telle méthode ferait probablement un this->find(key) != this->end() interne, mais considérez ce que vous faites lorsque la clé est effectivement présente; dans la plupart des cas, vous voudrez alors obtenir l’élément et en faire quelque chose. Cela signifie que vous devrez faire une seconde find() , ce qui est inefficace. Il est préférable d’utiliser directement la recherche, de sorte que vous pouvez mettre votre résultat en cache, comme ceci:

 Container::const_iterator it = myContainer.find(key); if (it != myContainer.end()) { // Do something with it, no more lookup needed. } else { // Key was not present. } 

Bien sûr, si vous ne vous souciez pas de l’efficacité, vous pouvez toujours faire votre propre choix, mais dans ce cas, vous ne devriez probablement pas utiliser C ++ …;)

Si vous deviez append une fonction contains , cela pourrait ressembler à ceci:

 #include  #include  template inline bool contains(TInputIterator first, TInputIterator last, const T& value) { return std::find(first, last, value) != last; } template inline bool contains(const TContainer& container, const T& value) { // This works with more containers but requires std::begin and std::end // from C++0x, which you can get either: // 1. By using a C++0x comstackr or // 2. Including the utility functions below. return contains(std::begin(container), std::end(container), value); // This works pre-C++0x (and without the utility functions below, but doesn't // work for fixed-length arrays. //return contains(container.begin(), container.end(), value); } template inline bool contains(const std::set& container, const T& value) { return container.find(value) != container.end(); } 

Cela fonctionne avec std::set , d’autres conteneurs STL et même des baies de longueur fixe:

 void test() { std::set set; set.insert(1); set.insert(4); assert(!contains(set, 3)); int set2[] = { 1, 2, 3 }; assert(contains(set2, 3)); } 

Modifier:

Comme indiqué dans les commentaires, j’ai involontairement utilisé une fonction nouvelle pour C ++ 0x ( std::begin et std::end ). Voici l’implémentation quasi sortingviale de VS2010:

 namespace std { template inline typename _Container::iterator begin(_Container& _Cont) { // get beginning of sequence return (_Cont.begin()); } template inline typename _Container::const_iterator begin(const _Container& _Cont) { // get beginning of sequence return (_Cont.begin()); } template inline typename _Container::iterator end(_Container& _Cont) { // get end of sequence return (_Cont.end()); } template inline typename _Container::const_iterator end(const _Container& _Cont) { // get end of sequence return (_Cont.end()); } template inline _Ty *begin(_Ty (&_Array)[_Size]) { // get beginning of array return (&_Array[0]); } template inline _Ty *end(_Ty (&_Array)[_Size]) { // get end of array return (&_Array[0] + _Size); } } 

Écrivez votre propre:

 template bool checkElementIsInSet(const T& elem, const std::set& container) { return container.find(elem) != container.end(); } 

Vous pouvez également vérifier si un élément est défini ou non lors de l’insertion de l’élément. La version à un seul élément renvoie une paire, avec son membre pair :: first défini sur un iterator pointant vers l’élément nouvellement inséré ou vers l’élément équivalent déjà présent dans l’ensemble. L’élément pair :: second de la paire est défini sur true si un nouvel élément a été inséré ou sur false si un élément équivalent existait déjà.

Par exemple: Supposons que l’ensemble comporte déjà 20 éléments.

  std::set myset; std::set::iterator it; std::pair::iterator,bool> ret; ret=myset.insert(20); if(ret.second==false) { //do nothing } else { //do something } it=ret.first //points to element 20 already in set. 

Si l’élément est nouvellement inséré, pair :: first désignera la position du nouvel élément dans l’ensemble.

j’utilise

 if(!my_set.count(that_element)) //Element is present... ; 

Mais ce n’est pas aussi efficace que

 if(my_set.find(that_element)!=my_set.end()) ....; 

Ma version ne me permet de gagner du temps que par l’écriture du code. Je le préfère de cette façon pour un codage compétitif.

J’ai pu écrire une fonction contains générales pour std::list et std::vector ,

 template bool contains( const list& container, const T& elt ) { return find( container.begin(), container.end(), elt ) != container.end() ; } template bool contains( const vector& container, const T& elt ) { return find( container.begin(), container.end(), elt ) != container.end() ; } // use: if( contains( yourList, itemInList ) ) // then do something 

Cela nettoie un peu la syntaxe.

Mais je n’ai pas pu utiliser le paramètre template template magic pour que cela fonctionne arbitrairement des conteneurs stl.

 // NOT WORKING: template class STLContainer, class T> bool contains( STLContainer container, T elt ) { return find( container.begin(), container.end(), elt ) != container.end() ; } 

Tout commentaire sur l’amélioration de la dernière réponse serait bien.

// syntaxe générale

  set::iterator ii = find(set1.begin(),set1.end(),"element to be searched"); 

/ * Dans le code ci-dessous, j’essaie de trouver l’élément 4 dans et int défini s’il est présent ou non * /

 set::iterator ii = find(set1.begin(),set1.end(),4); if(ii!=set1.end()) { cout<<"element found"; set1.erase(ii);// in case you want to erase that element from set. }