Tutto quello che voglio fare è verificare se esiste un elemento nel vettore o meno, in modo da poter affrontare ogni caso.
if ( item_present )
do_this();
else
do_that();
Tutto quello che voglio fare è verificare se esiste un elemento nel vettore o meno, in modo da poter affrontare ogni caso.
if ( item_present )
do_this();
else
do_that();
Risposte:
Puoi usare std::find
da <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()
Questo restituisce un bool ( true
se presente, false
altrimenti). Con il tuo esempio:
#include <algorithm>
#include <vector>
if ( std::find(vec.begin(), vec.end(), item) != vec.end() )
do_this();
else
do_that();
#include <algorithm>
o potresti ricevere errori molto strani come 'impossibile trovare la funzione di corrispondenza nello spazio dei nomi std'
.find()
è ancora non è una funzione di membro di std::vector
, come ci si aspetterebbe che dovrebbe essere? Mi chiedo se questa sia in qualche modo una conseguenza del templating.
std::vector<>::find()
non darebbe alcun vantaggio, né è necessario, quindi no, non dovrebbe essere un membro. Vedi anche en.wikipedia.org/wiki/Coupling_%28computer_programming%29
mvec.find(key) != mvec.cend()
è preferibile std::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend()
.
Come altri hanno già detto, utilizzare l'STL find
o le find_if
funzioni. Ma se siete alla ricerca in grandi vettori e questo influisce sulle prestazioni, si consiglia di ordinare la vostra vettoriale e quindi utilizzare i binary_search
, lower_bound
o upper_bound
algoritmi.
Usa find dall'intestazione dell'algoritmo di stl. Ho illustrato il suo uso con il tipo int. Puoi usare qualsiasi tipo ti piaccia purché sia possibile confrontare per uguaglianza (sovraccarico == se necessario per la propria classe personalizzata).
#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;
}
Se il tuo vettore non è ordinato, utilizza l'approccio suggerito da MSN:
if(std::find(vector.begin(), vector.end(), item)!=vector.end()){
// Found the item
}
Se il tuo vettore è ordinato, usa il metodo binary_search suggerito da Brian Neal:
if(binary_search(vector.begin(), vector.end(), item)){
// Found the item
}
la ricerca binaria produce le prestazioni del caso peggiore O (log n), che è molto più efficiente del primo approccio. Per utilizzare la ricerca binaria, è possibile utilizzare qsort per ordinare prima il vettore per garantire che sia ordinato.
std::sort
? qsort
è molto inefficiente sui vettori .... vedi: stackoverflow.com/questions/12308243/…
Uso qualcosa del genere ...
#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
... in questo modo è in realtà chiaro e leggibile. (Ovviamente puoi riutilizzare il modello in più punti).
value_type
dal contenitore per il tipo di elemento. Ho aggiunto una risposta come questa.
In C ++ 11 è possibile utilizzare any_of
. Ad esempio se è un vector<string> v;
allora:
if (any_of(v.begin(), v.end(), bind(equal_to<string>(), _1, item)))
do_this();
else
do_that();
In alternativa, usa un lambda:
if (any_of(v.begin(), v.end(), [&](const std::string& elem) { return elem == item; }))
do_this();
else
do_that();
bind1st
e bind2nd
sono deprecati dal C ++ 11 e completamente rimossi in C ++ 17. Utilizzare invece bind
con placeholders
e / o lambdas.
Ecco una funzione che funzionerà per qualsiasi contenitore:
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();
}
Si noti che è possibile cavarsela con 1 parametro del modello perché è possibile estrarre value_type
dal contenitore. È necessario il typename
perché Container::value_type
è un nome dipendente .
Tieni presente che, se hai intenzione di fare molte ricerche, ci sono contenitori STL che sono meglio per questo. Non so quale sia la tua applicazione, ma vale la pena prendere in considerazione contenitori associativi come std :: map.
std :: vector è il contenitore preferito a meno che tu non abbia una ragione per un'altra, e le ricerche in base al valore possono essere una tale ragione.
Utilizzare la funzione di ricerca STL .
Tieni presente che esiste anche una funzione find_if , che puoi utilizzare se la tua ricerca è più complessa, ad esempio se non stai solo cercando un elemento, ma, ad esempio, vuoi vedere se esiste un elemento che soddisfa un certo condizione, ad esempio, una stringa che inizia con "abc". ( find_if
ti darebbe un iteratore che punta al primo di questi elementi).
Con boost puoi usare any_of_equal
:
#include <boost/algorithm/cxx11/any_of.hpp>
bool item_present = boost::algorithm::any_of_equal(vector, element);
Puoi provare questo codice:
#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()
}
È possibile utilizzare la find
funzione, presente nello std
spazio dei nomi, ad es std::find
. Si passa la std::find
funzione the begin
e end
iteratore dal vettore che si desidera cercare, insieme all'elemento che si sta cercando e si confronta l'iteratore risultante con la fine del vettore per vedere se corrispondono o meno.
std::find(vector.begin(), vector.end(), item) != vector.end()
Puoi anche dereferenziare quell'iteratore e usarlo normalmente, come qualsiasi altro iteratore.
Puoi usare anche count. Restituirà il numero di elementi presenti in un vettore.
int t=count(vec.begin(),vec.end(),item);
find
è più veloce di count
, perché non continua a contare dopo la prima partita.
Se vuoi trovare una stringa in un vettore:
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 altro esempio che utilizza operatori 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 e versioni successive):
può usare std::search
anche
Questo è utile anche per la ricerca di sequenze di elementi.
#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;
}
Inoltre c'è la flessibilità di passare alcuni algoritmi di ricerca. Fare riferimento qui
Ho usato personalmente modelli di recente per gestire più tipi di contenitori contemporaneamente anziché occuparmi solo dei vettori. Ho trovato un esempio simile online (non ricordo dove), quindi il merito va a chiunque abbia rubato questo. Questo particolare modello sembra gestire anche array grezzi.
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);
}
L'utilizzo di Newton C ++ è più semplice, autocertificato e più rapido rispetto a std :: find a causa della restituzione di un bool direttamente.
bool exists_linear( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )
bool exists_binary( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )
Penso che sia ovvio cosa facciano le funzioni.
include <newton/algorithm/algorithm.hpp>
if ( newton::exists_linear(first, last, value) )
do_this();
else
do_that();