Tout ce que je veux faire, c'est vérifier si un élément existe dans le vecteur ou non, afin de pouvoir traiter chaque cas.
if ( item_present )
do_this();
else
do_that();
Tout ce que je veux faire, c'est vérifier si un élément existe dans le vecteur ou non, afin de pouvoir traiter chaque cas.
if ( item_present )
do_this();
else
do_that();
Réponses:
Vous pouvez utiliser à std::find
partir de <algorithm>
:
#include <vector>
vector<int> vec;
//can have other data types instead of int but must same datatype as item
std::find(vec.begin(), vec.end(), item) != vec.end()
Cela renvoie un booléen ( true
s'il est présent, false
sinon). Avec votre exemple:
#include <algorithm>
#include <vector>
if ( std::find(vec.begin(), vec.end(), item) != vec.end() )
do_this();
else
do_that();
#include <algorithm>
sinon vous pourriez obtenir des erreurs très étranges comme «
.find()
n'est toujours pas une fonction membre std::vector
, comme vous vous en doutez? Je me demande si c'est en quelque sorte une conséquence des modèles.
std::vector<>::find()
ne donnerait aucun avantage et n’est pas nécessaire. Par conséquent, non, il ne devrait pas être membre. Voir aussi en.wikipedia.org/wiki/Coupling_%28computer_programming%29
mvec.find(key) != mvec.cend()
est préférable à std::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend()
.
Comme d'autres l'ont dit, utilisez la STL find
ou les find_if
fonctions. Mais si vous êtes à la recherche dans des vecteurs très importants et cette performance impacts, vous pouvez trier votre vecteur, puis utilisez les binary_search
, lower_bound
ou des upper_bound
algorithmes.
Utilisez find à partir de l'en-tête de l'algorithme de stl. J'ai illustré son utilisation avec le type int. Vous pouvez utiliser n'importe quel type que vous aimez tant que vous pouvez comparer pour l'égalité (surcharge == si vous en avez besoin pour votre classe personnalisée).
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
typedef vector<int> IntContainer;
typedef IntContainer::iterator IntIterator;
IntContainer vw;
//...
// find 5
IntIterator i = find(vw.begin(), vw.end(), 5);
if (i != vw.end()) {
// found it
} else {
// doesn't exist
}
return 0;
}
Si votre vecteur n'est pas ordonné, utilisez l'approche suggérée par MSN:
if(std::find(vector.begin(), vector.end(), item)!=vector.end()){
// Found the item
}
Si votre vecteur est ordonné, utilisez la méthode binary_search Brian Neal a suggéré:
if(binary_search(vector.begin(), vector.end(), item)){
// Found the item
}
la recherche binaire donne les performances du pire des cas O (log n), ce qui est beaucoup plus efficace que la première approche. Afin d'utiliser la recherche binaire, vous pouvez utiliser qsort pour trier d'abord le vecteur pour garantir qu'il est ordonné.
std::sort
? qsort
est très inefficace sur les vecteurs .... voir: stackoverflow.com/questions/12308243/…
J'utilise quelque chose comme ça ...
#include <algorithm>
template <typename T>
const bool Contains( std::vector<T>& Vec, const T& Element )
{
if (std::find(Vec.begin(), Vec.end(), Element) != Vec.end())
return true;
return false;
}
if (Contains(vector,item))
blah
else
blah
... comme ça c'est en fait clair et lisible. (Évidemment, vous pouvez réutiliser le modèle à plusieurs endroits).
value_type
le conteneur pour le type d'élément. J'ai ajouté une réponse comme celle-ci.
En C ++ 11, vous pouvez utiliser any_of
. Par exemple, si c'est un vector<string> v;
alors:
if (any_of(v.begin(), v.end(), bind(equal_to<string>(), _1, item)))
do_this();
else
do_that();
Vous pouvez également utiliser un lambda:
if (any_of(v.begin(), v.end(), [&](const std::string& elem) { return elem == item; }))
do_this();
else
do_that();
bind1st
et bind2nd
sont obsolètes depuis C ++ 11 et complètement supprimés en C ++ 17. Utilisez plutôt bind
avec placeholders
et / ou lambdas.
Voici une fonction qui fonctionnera pour n'importe quel conteneur:
template <class Container>
const bool contains(const Container& container, const typename Container::value_type& element)
{
return std::find(container.begin(), container.end(), element) != container.end();
}
Notez que vous pouvez vous en tirer avec 1 paramètre de modèle, car vous pouvez extraire le value_type
du conteneur. Vous avez besoin du typename
car Container::value_type
est un nom dépendant .
Gardez à l'esprit que, si vous effectuez de nombreuses recherches, il existe des conteneurs STL qui conviennent mieux à cela. Je ne sais pas quelle est votre application, mais les conteneurs associatifs comme std :: map peuvent être intéressants.
std :: vector est le conteneur de choix, sauf si vous avez une raison pour une autre, et les recherches par valeur peuvent être une telle raison.
Utilisez la fonction de recherche STL .
Gardez à l'esprit qu'il existe également une fonction find_if , que vous pouvez utiliser si votre recherche est plus complexe, c'est-à-dire si vous ne recherchez pas seulement un élément, mais, par exemple, vous voulez voir s'il y a un élément qui remplit un certain condition, par exemple, une chaîne commençant par "abc". ( find_if
vous donnerait un itérateur qui pointe vers le premier élément de ce type).
Avec boost, vous pouvez utiliser any_of_equal
:
#include <boost/algorithm/cxx11/any_of.hpp>
bool item_present = boost::algorithm::any_of_equal(vector, element);
Vous pouvez essayer ce code:
#include <algorithm>
#include <vector>
// You can use class, struct or primitive data type for Item
struct Item {
//Some fields
};
typedef std::vector<Item> ItemVector;
typedef ItemVector::iterator ItemIterator;
//...
ItemVector vtItem;
//... (init data for vtItem)
Item itemToFind;
//...
ItemIterator itemItr;
itemItr = std::find(vtItem.begin(), vtItem.end(), itemToFind);
if (itemItr != vtItem.end()) {
// Item found
// doThis()
}
else {
// Item not found
// doThat()
}
Vous pouvez utiliser la find
fonction, trouvée dans l' std
espace de noms, c'est-à-dire std::find
. Vous passez la std::find
fonction begin
et l' end
itérateur du vecteur que vous souhaitez rechercher, ainsi que l'élément que vous recherchez et comparez l'itérateur résultant à la fin du vecteur pour voir s'ils correspondent ou non.
std::find(vector.begin(), vector.end(), item) != vector.end()
Vous pouvez également déréférencer cet itérateur et l'utiliser normalement, comme n'importe quel autre itérateur.
Vous pouvez également utiliser le comptage. Il renverra le nombre d'éléments présents dans un vecteur.
int t=count(vec.begin(),vec.end(),item);
find
est plus rapide que count
, car il ne continue pas de compter après le premier match.
Si vous voulez trouver une chaîne dans un vecteur:
struct isEqual
{
isEqual(const std::string& s): m_s(s)
{}
bool operator()(OIDV* l)
{
return l->oid == m_s;
}
std::string m_s;
};
struct OIDV
{
string oid;
//else
};
VecOidv::iterator itFind=find_if(vecOidv.begin(),vecOidv.end(),isEqual(szTmp));
Un autre exemple utilisant des opérateurs C ++.
#include <vector>
#include <algorithm>
#include <stdexcept>
template<typename T>
inline static bool operator ==(const std::vector<T>& v, const T& elem)
{
return (std::find(v.begin(), v.end(), elem) != v.end());
}
template<typename T>
inline static bool operator !=(const std::vector<T>& v, const T& elem)
{
return (std::find(v.begin(), v.end(), elem) == v.end());
}
enum CODEC_ID {
CODEC_ID_AAC,
CODEC_ID_AC3,
CODEC_ID_H262,
CODEC_ID_H263,
CODEC_ID_H264,
CODEC_ID_H265,
CODEC_ID_MAX
};
void main()
{
CODEC_ID codec = CODEC_ID_H264;
std::vector<CODEC_ID> codec_list;
codec_list.reserve(CODEC_ID_MAX);
codec_list.push_back(CODEC_ID_AAC);
codec_list.push_back(CODEC_ID_AC3);
codec_list.push_back(CODEC_ID_H262);
codec_list.push_back(CODEC_ID_H263);
codec_list.push_back(CODEC_ID_H264);
codec_list.push_back(CODEC_ID_H265);
if (codec_list != codec)
{
throw std::runtime_error("codec not found!");
}
if (codec_list == codec)
{
throw std::logic_error("codec has been found!");
}
}
template <typename T> bool IsInVector(T what, std::vector<T> * vec)
{
if(std::find(vec->begin(),vec->end(),what)!=vec->end())
return true;
return false;
}
(C ++ 17 et supérieur):
peut std::search
également utiliser
Ceci est également utile pour rechercher une séquence d'éléments.
#include <algorithm>
#include <iostream>
#include <vector>
template <typename Container>
bool search_vector(const Container& vec, const Container& searchvec)
{
return std::search(vec.begin(), vec.end(), searchvec.begin(), searchvec.end()) != vec.end();
}
int main()
{
std::vector<int> v = {2,4,6,8};
//THIS WORKS. SEARCHING ONLY ONE ELEMENT.
std::vector<int> searchVector1 = {2};
if(search_vector(v,searchVector1))
std::cout<<"searchVector1 found"<<std::endl;
else
std::cout<<"searchVector1 not found"<<std::endl;
//THIS WORKS, AS THE ELEMENTS ARE SEQUENTIAL.
std::vector<int> searchVector2 = {6,8};
if(search_vector(v,searchVector2))
std::cout<<"searchVector2 found"<<std::endl;
else
std::cout<<"searchVector2 not found"<<std::endl;
//THIS WILL NOT WORK, AS THE ELEMENTS ARE NOT SEQUENTIAL.
std::vector<int> searchVector3 = {8,6};
if(search_vector(v,searchVector3))
std::cout<<"searchVector3 found"<<std::endl;
else
std::cout<<"searchVector3 not found"<<std::endl;
}
Il est également possible de passer certains algorithmes de recherche. Reportez-vous ici.
J'ai personnellement utilisé des modèles récemment pour gérer plusieurs types de conteneurs à la fois plutôt que de traiter uniquement des vecteurs. J'ai trouvé un exemple similaire en ligne (je ne me souviens pas d'où), donc le mérite revient à qui que ce soit. Ce modèle particulier semble également gérer les tableaux bruts.
template <typename Container, typename T = typename std::decay<decltype(*std::begin(std::declval<Container>()))>::type>
bool contains(Container && c, T v)
{
return std::find(std::begin(c), std::end(c), v) != std::end(c);
}
Utiliser Newton C ++ est plus facile, auto-documenté et plus rapide qu'avec std :: find car il renvoie directement un booléen.
bool exists_linear( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )
bool exists_binary( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )
Je pense que c'est évident ce que font les fonctions.
include <newton/algorithm/algorithm.hpp>
if ( newton::exists_linear(first, last, value) )
do_this();
else
do_that();