Ich möchte nur überprüfen, ob ein Element im Vektor vorhanden ist oder nicht, damit ich mich mit jedem Fall befassen kann.
if ( item_present )
do_this();
else
do_that();
Ich möchte nur überprüfen, ob ein Element im Vektor vorhanden ist oder nicht, damit ich mich mit jedem Fall befassen kann.
if ( item_present )
do_this();
else
do_that();
Antworten:
Sie können verwenden std::find
von <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()
Dies gibt einen Bool zurück ( true
falls vorhanden, false
andernfalls). Mit Ihrem Beispiel:
#include <algorithm>
#include <vector>
if ( std::find(vec.begin(), vec.end(), item) != vec.end() )
do_this();
else
do_that();
#include <algorithm>
sonst könnten sehr seltsame Fehler wie "
.find()
immer noch keine Mitgliedsfunktion von ist std::vector
, wie Sie es erwarten würden? Ich frage mich, ob dies irgendwie eine Folge von Vorlagen ist.
std::vector<>::find()
würde keinen Vorteil geben, noch ist es erforderlich, daher nein, es sollte kein Mitglied sein. Siehe auch en.wikipedia.org/wiki/Coupling_%28computer_programming%29
mvec.find(key) != mvec.cend()
ist vorzuziehen std::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend()
.
Verwenden Sie, wie bereits erwähnt, die STL find
oder find_if
Funktionen. Aber wenn man in sehr großen Vektoren und diese Auswirkungen Leistung sucht, mögen Sie vielleicht Ihren Vektor sortieren und dann mit dem binary_search
, lower_bound
oder upper_bound
Algorithmen.
Verwenden Sie find aus dem Algorithmus-Header von stl. Ich habe die Verwendung mit dem Typ int veranschaulicht. Sie können einen beliebigen Typ verwenden, solange Sie ihn auf Gleichheit vergleichen können (Überladung ==, falls erforderlich, für Ihre benutzerdefinierte Klasse).
#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;
}
Wenn Ihr Vektor nicht geordnet ist, verwenden Sie den von MSN vorgeschlagenen Ansatz:
if(std::find(vector.begin(), vector.end(), item)!=vector.end()){
// Found the item
}
Wenn Ihr Vektor geordnet ist, verwenden Sie die von Brian Neal vorgeschlagene Methode binary_search:
if(binary_search(vector.begin(), vector.end(), item)){
// Found the item
}
Die binäre Suche ergibt eine O (log n) Worst-Case-Leistung, die weitaus effizienter ist als der erste Ansatz. Um die binäre Suche zu verwenden, können Sie den Vektor zuerst mit qsort sortieren, um sicherzustellen, dass er geordnet ist.
std::sort
? qsort
ist sehr ineffizient auf Vektoren .... siehe: stackoverflow.com/questions/12308243/…
Ich benutze so etwas ...
#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
... so ist es eigentlich klar und lesbar. (Natürlich können Sie die Vorlage an mehreren Stellen wiederverwenden.)
value_type
aus dem Container für den Elementtyp verwenden. Ich habe eine Antwort wie diese hinzugefügt.
In C ++ 11 können Sie verwenden any_of
. Zum Beispiel, wenn es ein vector<string> v;
Dann ist:
if (any_of(v.begin(), v.end(), bind(equal_to<string>(), _1, item)))
do_this();
else
do_that();
Alternativ können Sie ein Lambda verwenden:
if (any_of(v.begin(), v.end(), [&](const std::string& elem) { return elem == item; }))
do_this();
else
do_that();
bind1st
und bind2nd
sind seit C ++ 11 veraltet und in C ++ 17 vollständig entfernt. Verwenden Sie stattdessen bind
mit placeholders
und / oder Lambdas.
Hier ist eine Funktion, die für jeden Container funktioniert:
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();
}
Beachten Sie, dass Sie mit 1 Vorlagenparameter davonkommen können, da Sie die value_type
aus dem Container extrahieren können . Sie benötigen das typename
weil Container::value_type
ist ein abhängiger Name .
Denken Sie daran, dass es STL-Container gibt, die dafür besser geeignet sind, wenn Sie viele Suchvorgänge durchführen. Ich weiß nicht, was Ihre Anwendung ist, aber assoziative Container wie std :: map sind möglicherweise eine Überlegung wert.
std :: vector ist der Container der Wahl, es sei denn, Sie haben einen Grund für einen anderen, und die Suche nach Wert kann ein solcher Grund sein.
Verwenden Sie die STL- Suchfunktion .
Beachten Sie, dass es auch eine find_if- Funktion gibt, die Sie verwenden können, wenn Ihre Suche komplexer ist, dh wenn Sie nicht nur nach einem Element suchen, sondern beispielsweise sehen möchten, ob es ein Element gibt, das eine bestimmte Funktion erfüllt Bedingung ist beispielsweise eine Zeichenfolge, die mit "abc" beginnt. ( find_if
würde Ihnen einen Iterator geben, der auf das erste derartige Element zeigt).
Mit Boost können Sie verwenden any_of_equal
:
#include <boost/algorithm/cxx11/any_of.hpp>
bool item_present = boost::algorithm::any_of_equal(vector, element);
Sie können diesen Code ausprobieren:
#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()
}
Sie können die find
Funktion verwenden, die sich im std
Namespace befindet, dh std::find
. Sie übergeben die std::find
Funktion begin
und den end
Iterator des zu suchenden Vektors zusammen mit dem gesuchten Element und vergleichen den resultierenden Iterator mit dem Ende des Vektors, um festzustellen, ob sie übereinstimmen oder nicht.
std::find(vector.begin(), vector.end(), item) != vector.end()
Sie können diesen Iterator auch dereferenzieren und wie jeden anderen Iterator wie gewohnt verwenden.
Sie können auch count verwenden. Es wird die Anzahl der in einem Vektor vorhandenen Elemente zurückgegeben.
int t=count(vec.begin(),vec.end(),item);
find
ist schneller als count
, weil es nach dem ersten Spiel nicht mehr zählt.
Wenn Sie eine Zeichenfolge in einem Vektor finden möchten:
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));
Ein weiteres Beispiel mit C ++ - Operatoren.
#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 und höher):
kann std::search
auch verwenden
Dies ist auch nützlich für die Suche nach einer Folge von Elementen.
#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;
}
Es besteht auch die Flexibilität, einige Suchalgorithmen zu übergeben. Siehe hier.
Ich habe in letzter Zeit persönlich Vorlagen verwendet, um mehrere Arten von Containern gleichzeitig zu verarbeiten, anstatt nur Vektoren zu behandeln. Ich habe ein ähnliches Beispiel online gefunden (kann mich nicht erinnern, wo), also geht der Kredit an denjenigen, von dem ich das gestohlen habe. Dieses spezielle Muster scheint auch mit rohen Arrays umzugehen.
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);
}
Mit Newton C ++ ist es einfacher, selbstdokumentierter und schneller als mit std :: find, da ein Bool direkt zurückgegeben wird.
bool exists_linear( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )
bool exists_binary( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )
Ich denke, es ist offensichtlich, was die Funktionen tun.
include <newton/algorithm/algorithm.hpp>
if ( newton::exists_linear(first, last, value) )
do_this();
else
do_that();