in einem Vektor der Suche ist sehr langsam , da Sie bei jedem einzelnen Elemente des Vektors suchen haben , so sollten Sie eine Karte verwenden , wenn Sie eine Menge Lookups tun
naumcho
7
@naumcho: Wenn der Vektor sortiert ist, gibt es immer eine binäre Suche, wie unten angegeben. Dies macht es so schnell wie eine Karte und wenn Sie nur Werte speichern (keine Schlüssel- / Wertekarten), wird es viel weniger Speicher verbrauchen.
Adam Hawes
4
Karten sind sicherlich nicht die beste Wahl, aber die Verwendung von Set kann nützlich sein. Wenn Sie eine Suchzeit von O (1) benötigen, ist hash_set der richtige Weg.
#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 ( truefalls vorhanden, falseandernfalls). Mit Ihrem Beispiel:
Ich sehe nicht, wie count () schneller sein könnte als find (), da find () stoppt, sobald ein Element gefunden wird, während count () immer die gesamte Sequenz scannen muss.
Éric Malenfant
114
Vergessen Sie nicht, #include <algorithm>sonst könnten sehr seltsame Fehler wie "
Ich
80
Hat es niemanden gestört, dass die STL, obwohl sie "objektorientiert" ist, .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.
Bobobobo
71
@bobobobo: OOP hat nichts mit Mitgliedern oder Nichtmitgliedern zu tun. Und es gibt eine weit verbreitete Denkrichtung: Wenn etwas kein Mitglied sein muss oder wenn es bei der Implementierung als Mitglied keinen Vorteil bringt, sollte es kein Mitglied sein. 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
Sebastian Mach
36
@phresnel Ich würde argumentieren, dass "wenn es keinen Vorteil bringt, wenn es als Mitglied implementiert wird" für diesen Fall falsch ist. Der Vorteil ist eine vereinfachte und übersichtlichere Oberfläche. Zum Beispiel: mvec.find(key) != mvec.cend()ist vorzuziehen std::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend().
Swalog
113
Verwenden Sie, wie bereits erwähnt, die STL findoder find_ifFunktionen. 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_boundoder upper_boundAlgorithmen.
Gute Antwort! Finden ist immer o (n). lower_bound ist o (log (n)), wenn es mit Iteratoren mit wahlfreiem Zugriff verwendet wird.
Stephen Edmonds
30
Das Sortieren ist jedoch O (nlogn), daher lohnt es sich nur, wenn Sie mehr als O (logn) suchen.
Liori
7
@liori Richtig, es hängt von Ihren Nutzungsmustern ab. Wenn Sie es nur einmal sortieren müssen, führen Sie wiederholt viele Suchvorgänge durch, um Sie zu retten.
Brian Neal
1
@ Brian Neal, das Sortieren eines großen Vektors lohnt sich, wenn viele Elementsuchen durchgeführt werden müssen. Die Sortierung ist O (nlogn) und O (n) ist besser, wenn man ein Element nur einmal finden muss :)
Swapnil B.
47
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>usingnamespace std;int main(){typedefvector<int>IntContainer;typedefIntContainer::iteratorIntIterator;IntContainer vw;//...// find 5IntIterator i = find(vw.begin(), vw.end(),5);if(i != vw.end()){// found it}else{// doesn't exist}return0;}
Abhängig von den Anforderungen des OP kann auch find_if () geeignet sein. Es ermöglicht die Suche mit einem beliebigen Prädikat anstelle von Gleichheit.
Éric Malenfant
Hoppla, habe deinen Kommentar zu spät gesehen. Die Antwort, die ich gab, erwähnt auch find_if.
Frank
39
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.
Die binäre Suche ist bei größeren Containern besser, bei kleinen Containern ist eine einfache lineare Suche jedoch wahrscheinlich genauso schnell oder schneller.
und Sie können es für Listen oder Vektoren arbeiten lassen, indem Sie 2 Typnamen verwenden
Erik Aronesty
@ErikAronesty Sie können mit 1 Vorlagenargument davonkommen, wenn Sie value_typeaus dem Container für den Elementtyp verwenden. Ich habe eine Antwort wie diese hinzugefügt.
Martin Broadhurst
13
In C ++ 11 können Sie verwenden any_of. Zum Beispiel, wenn es ein vector<string> v;Dann ist:
Beachten Sie, dass Sie mit 1 Vorlagenparameter davonkommen können, da Sie die value_typeaus dem Container extrahieren können . Sie benötigen das typenameweil Container::value_typeist ein abhängiger Name .
Beachten Sie, dass dies manchmal etwas zu weit gefasst ist - es funktioniert beispielsweise für std :: set, bietet aber im Vergleich zur Funktion find () member eine schreckliche Leistung. Ich habe es am besten gefunden, eine Spezialisierung für Container mit einer schnelleren Suche hinzuzufügen (set / map, unordered_ *)
Andy Krouwel
10
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.
Selbst bei der Suche nach Wert kann der Vektor eine gute Wahl sein, solange er sortiert ist und Sie binäre Suche, untere Grenze oder obere Grenze verwenden. Wenn sich der Inhalt des Containers zwischen den Suchvorgängen ändert, ist der Vektor nicht sehr gut, da erneut sortiert werden muss.
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_ifwürde Ihnen einen Iterator geben, der auf das erste derartige Element zeigt).
#include<algorithm>#include<vector>// You can use class, struct or primitive data type for ItemstructItem{//Some fields};typedef std::vector<Item>ItemVector;typedefItemVector::iteratorItemIterator;//...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 findFunktion verwenden, die sich im stdNamespace befindet, dh std::find. Sie übergeben die std::findFunktion beginund den endIterator 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.
Dies ist auch nützlich für die Suche nach einer Folge von Elementen.
#include<algorithm>#include<iostream>#include<vector>template<typenameContainer>bool search_vector(constContainer& vec,constContainer& 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<typenameContainer,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);}
Antworten:
Sie können verwenden
std::find
von<algorithm>
:Dies gibt einen Bool zurück (
true
falls vorhanden,false
andernfalls). Mit Ihrem Beispiel:quelle
#include <algorithm>
sonst könnten sehr seltsame Fehler wie ".find()
immer noch keine Mitgliedsfunktion von iststd::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%29mvec.find(key) != mvec.cend()
ist vorzuziehenstd::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend()
.Verwenden Sie, wie bereits erwähnt, die STL
find
oderfind_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 dembinary_search
,lower_bound
oderupper_bound
Algorithmen.quelle
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).
quelle
Wenn Ihr Vektor nicht geordnet ist, verwenden Sie den von MSN vorgeschlagenen Ansatz:
Wenn Ihr Vektor geordnet ist, verwenden Sie die von Brian Neal vorgeschlagene Methode binary_search:
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.
quelle
std::sort
?qsort
ist sehr ineffizient auf Vektoren .... siehe: stackoverflow.com/questions/12308243/…Ich benutze so etwas ...
... so ist es eigentlich klar und lesbar. (Natürlich können Sie die Vorlage an mehreren Stellen wiederverwenden.)
quelle
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 einvector<string> v;
Dann ist:Alternativ können Sie ein Lambda verwenden:
quelle
bind1st
undbind2nd
sind seit C ++ 11 veraltet und in C ++ 17 vollständig entfernt. Verwenden Sie stattdessenbind
mitplaceholders
und / oder Lambdas.Hier ist eine Funktion, die für jeden Container funktioniert:
Beachten Sie, dass Sie mit 1 Vorlagenparameter davonkommen können, da Sie die
value_type
aus dem Container extrahieren können . Sie benötigen dastypename
weilContainer::value_type
ist ein abhängiger Name .quelle
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.
quelle
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).quelle
Mit Boost können Sie verwenden
any_of_equal
:quelle
Sie können diesen Code ausprobieren:
quelle
Sie können die
find
Funktion verwenden, die sich imstd
Namespace befindet, dhstd::find
. Sie übergeben diestd::find
Funktionbegin
und denend
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.Sie können diesen Iterator auch dereferenzieren und wie jeden anderen Iterator wie gewohnt verwenden.
quelle
Sie können auch count verwenden. Es wird die Anzahl der in einem Vektor vorhandenen Elemente zurückgegeben.
quelle
find
ist schneller alscount
, weil es nach dem ersten Spiel nicht mehr zählt.Wenn Sie eine Zeichenfolge in einem Vektor finden möchten:
quelle
Ein weiteres Beispiel mit C ++ - Operatoren.
quelle
quelle
(C ++ 17 und höher):
kann
std::search
auch verwendenDies ist auch nützlich für die Suche nach einer Folge von Elementen.
Es besteht auch die Flexibilität, einige Suchalgorithmen zu übergeben. Siehe hier.
https://en.cppreference.com/w/cpp/algorithm/search
quelle
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.
quelle
Mit Newton C ++ ist es einfacher, selbstdokumentierter und schneller als mit std :: find, da ein Bool direkt zurückgegeben wird.
Ich denke, es ist offensichtlich, was die Funktionen tun.
quelle