Cómo comprobar que un elemento está en un std::set?


¿Cómo se comprueba que un elemento está en un conjunto?

¿Existe un equivalente más simple del siguiente código:

myset.find(x) != myset.end()
Author: Lightness Races in Orbit, 2009-11-09

9 answers

La forma típica de comprobar la existencia en muchos contenedores STL es:

const bool is_in = container.find(element) != container.end();
 300
Author: unwind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-09 17:39:19

Otra forma de simplemente decir si un elemento existe es comprobar el count()

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

La mayoría de las veces, sin embargo, me encuentro necesitando acceso al elemento donde quiera que verifique su existencia.

Así que tendría que encontrar el iterador de todos modos. Entonces, por supuesto, es mejor simplemente compararlo con end también.

set< X >::iterator it = myset.find(x);
if (it != myset.end()) {
   // do something with *it
}
 153
Author: Pieter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-09 15:42:31

Solo para aclarar, la razón por la que no hay un miembro como contains() en estos tipos de contenedores es porque te abriría a escribir código ineficiente. Tal método probablemente solo haría un this->find(key) != this->end() internamente, pero considere lo que hace cuando la clave está realmente presente; en la mayoría de los casos, querrá obtener el elemento y hacer algo con él. Esto significa que tendrías que hacer un segundo find(), lo cual es ineficiente. Es mejor usar buscar directamente, para que puedas almacenar en caché tu resultado, como entonces:

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

Por supuesto, si no te importa la eficiencia, siempre puedes rodar la tuya, pero en ese caso probablemente no deberías usar C++... ;)

 35
Author: Tim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-09 16:26:59

Si vas a agregar una función contains, podría verse así:

#include <algorithm>
#include <iterator>

template<class TInputIterator, class T> inline
bool contains(TInputIterator first, TInputIterator last, const T& value)
{
    return std::find(first, last, value) != last;
}

template<class TContainer, class T> 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 compiler 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<class T> inline
bool contains(const std::set<T>& container, const T& value)
{
    return container.find(value) != container.end();
}

Esto funciona con std::set, otros contenedores STL, e incluso arreglos de longitud fija:

void test()
{
    std::set<int> set;
    set.insert(1);
    set.insert(4);
    assert(!contains(set, 3));

    int set2[] = { 1, 2, 3 };
    assert(contains(set2, 3));
}

Editar:

Como se señaló en los comentarios, sin querer usé una función nueva para C++0x (std::begin y std::end). Aquí está la implementación casi trivial de VS2010:

namespace std {

template<class _Container> inline
    typename _Container::iterator begin(_Container& _Cont)
    { // get beginning of sequence
    return (_Cont.begin());
    }

template<class _Container> inline
    typename _Container::const_iterator begin(const _Container& _Cont)
    { // get beginning of sequence
    return (_Cont.begin());
    }

template<class _Container> inline
    typename _Container::iterator end(_Container& _Cont)
    { // get end of sequence
    return (_Cont.end());
    }

template<class _Container> inline
    typename _Container::const_iterator end(const _Container& _Cont)
    { // get end of sequence
    return (_Cont.end());
    }

template<class _Ty,
    size_t _Size> inline
    _Ty *begin(_Ty (&_Array)[_Size])
    { // get beginning of array
    return (&_Array[0]);
    }

template<class _Ty,
    size_t _Size> inline
    _Ty *end(_Ty (&_Array)[_Size])
    { // get end of array
    return (&_Array[0] + _Size);
    }

}
 6
Author: Sam Harwell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-09 17:21:45

También puede comprobar si un elemento está en set o no mientras inserta el elemento. La versión de elemento único devuelve un par, con su par miembro::first establecido en un iterador que apunta al elemento recién insertado o al elemento equivalente que ya está en el conjunto. El segundo elemento pair::en el par se establece en true si se insertó un nuevo elemento o false si ya existía un elemento equivalente.

Por ejemplo: Supongamos que el conjunto ya tiene 20 como elemento.

 std::set<int> myset;
 std::set<int>::iterator it;
 std::pair<std::set<int>::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 el elemento se inserta recientemente que pair:: first apuntará a la posición del nuevo elemento en set.

 3
Author: Prashant Shubham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-15 17:42:01

Escribe el tuyo:

template<class T>
bool checkElementIsInSet(const T& elem, const std::set<T>& container)
{
  return container.find(elem) != container.end();
}
 2
Author: stefaanv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-09 13:59:28

Utilizo

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

, Pero no es tan eficiente como

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

Mi versión solo me ahorra tiempo al escribir el código. Lo prefiero de esta manera para la codificación competitiva.

 1
Author: Manas Bondale,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-03 10:41:00

Pude escribir una función general contains para std::list y std::vector,

template<typename T>
bool contains( const list<T>& container, const T& elt )
{
  return find( container.begin(), container.end(), elt ) != container.end() ;
}

template<typename T>
bool contains( const vector<T>& container, const T& elt )
{
  return find( container.begin(), container.end(), elt ) != container.end() ;
}

// use:
if( contains( yourList, itemInList ) ) // then do something

Esto limpia un poco la sintaxis.

Pero no pude usar template template parameter magic para hacer que este trabajo sea arbitrario en contenedores stl.

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

Cualquier comentario sobre la mejora de la última respuesta sería agradable.

 0
Author: bobobobo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:38

//sintaxis general

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

/ * en el siguiente código estoy tratando de encontrar el elemento 4 in e int set si está presente o no* /

set<int>::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.
 }
 0
Author: sanjeev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-04 11:27:13