如何检查一个元素是在一个std :: set?
你如何检查一个元素是在一个集合?
有一个更简单的相当于下面的代码:
myset.find(x) != myset.end()
在许多STL容器中检查存在的典型方法是:
const bool is_in = container.find(element) != container.end();
简单地告诉一个元素是否存在的另一种方法是检查count()
if (myset.count(x)) { // x is in the set, count is 1 } else { // count zero, ie x not in the set }
但是,大多数情况下,我发现自己需要访问元素,无论我检查它的存在。
所以我不得不find迭代器。 那么当然,最好简单的比较一下。
set< X >::iterator it = myset.find(x); if (it != myset.end()) { // do something with *it }
只是为了澄清,在这些容器types中没有像contains()
这样的成员的原因是因为它会打开你编写低效的代码。 这样的方法可能只是在内部做一个this->find(key) != this->end()
,但是当key真的存在时, 在大多数情况下,你会想要得到的元素,并做一些事情。 这意味着你必须做第二次find()
,这是效率低下的。 最好直接使用find,这样可以caching结果,如下所示:
Container::const_iterator it = myContainer.find(key); if (it != myContainer.end()) { // Do something with it, no more lookup needed. } else { // Key was not present. }
当然,如果你不关心效率,你总是可以推出自己的,但在这种情况下,你可能不应该使用C ++ …;)
如果你要添加一个contains
函数,它可能看起来像这样:
#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(); }
这适用于std::set
,其他STL容器,甚至固定长度的数组:
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)); }
编辑:
正如在注释中指出的那样,我无意中使用了一个新的C ++ 0x( std::begin
和std::end
)函数。 这里是从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); } }
写你自己的:
template<class T> bool checkElementIsInSet(const T& elem, const std::set<T>& container) { return container.find(elem) != container.end(); }
插入元素时,您还可以检查元素是否处于设置状态。 单个元素版本返回一个对,其成员对::首先设置为一个迭代器,指向新插入的元素或已经在集合中的等价元素。 如果插入新元素,则将pair中的pair :: second元素设置为true;如果已经存在等效元素,则将该元素设置为false。
例如:假设集合已经有20个元素。
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.
如果新插入的元素比pair :: first将指向set中新元素的位置。
我可以写一个普通的contains
std::list
和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
这清理了一下语法。
但是我不能使用模板模板参数魔术来使这个工作任意的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() ; }
任何关于改善最后答案的意见将是很好的。
//一般语法
set<int>::iterator ii = find(set1.begin(),set1.end(),"element to be searched");
/ *在下面的代码中我试图find元素4和int集如果它是否存在* /
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. }