Wszystko, co chcę zrobić, to sprawdzić, czy element istnieje w wektorze, czy nie, więc mogę poradzić sobie z każdym przypadkiem.
if ( item_present )
do_this();
else
do_that();
Wszystko, co chcę zrobić, to sprawdzić, czy element istnieje w wektorze, czy nie, więc mogę poradzić sobie z każdym przypadkiem.
if ( item_present )
do_this();
else
do_that();
Odpowiedzi:
Możesz używać std::find
z <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()
Zwraca bool ( true
jeśli jest obecny, w false
przeciwnym razie). Na przykład:
#include <algorithm>
#include <vector>
if ( std::find(vec.begin(), vec.end(), item) != vec.end() )
do_this();
else
do_that();
#include <algorithm>
bo mogą się pojawić bardzo dziwne błędy, takie jak „nie można znaleźć pasującej funkcji w przestrzeni nazw std”
.find()
wciąż nie jest funkcją członka std::vector
, jak można się spodziewać? Zastanawiam się, czy jest to w jakiś sposób konsekwencja szablonowania.
std::vector<>::find()
nie dałoby żadnej korzyści, ani też nie jest potrzebne, dlatego nie, nie powinien być członkiem. Zobacz także en.wikipedia.org/wiki/Coupling_%28computer_programming%29
mvec.find(key) != mvec.cend()
lepiej niż std::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend()
.
Jak powiedzieli inni, użyj STL find
lub find_if
funkcji. Ale jeśli szukasz w bardzo dużych wektorów i wydajność to wpływ, może chcesz uporządkować swoje wektor a następnie użyć binary_search
, lower_bound
lub upper_bound
algorytmów.
Użyj find z nagłówka algorytmu stl. Zilustrowałem jego użycie typem int. Możesz użyć dowolnego typu, pod warunkiem, że możesz porównać dla równości (przeciążenie ==, jeśli potrzebujesz dla swojej klasy niestandardowej).
#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;
}
Jeśli twój wektor nie jest uporządkowany, użyj sugerowanego przez MSN podejścia:
if(std::find(vector.begin(), vector.end(), item)!=vector.end()){
// Found the item
}
Jeśli twój wektor jest uporządkowany, użyj metody binary_search Brian Neal zasugerował:
if(binary_search(vector.begin(), vector.end(), item)){
// Found the item
}
wyszukiwanie binarne daje wydajność O (log n) w najgorszym przypadku, która jest znacznie wydajniejsza niż pierwsze podejście. Aby użyć wyszukiwania binarnego, możesz użyć qsort, aby najpierw posortować wektor, aby upewnić się, że jest on uporządkowany.
std::sort
? qsort
jest bardzo nieefektywny w przypadku wektorów .... patrz: stackoverflow.com/questions/12308243/...
Używam czegoś takiego ...
#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
... w ten sposób jest to właściwie jasne i czytelne. (Oczywiście możesz ponownie użyć szablonu w wielu miejscach).
value_type
z kontenera dla typu elementu. Dodałem taką odpowiedź.
W C ++ 11 możesz używać any_of
. Na przykład jeśli jest to vector<string> v;
wtedy:
if (any_of(v.begin(), v.end(), bind(equal_to<string>(), _1, item)))
do_this();
else
do_that();
Alternatywnie użyj lambda:
if (any_of(v.begin(), v.end(), [&](const std::string& elem) { return elem == item; }))
do_this();
else
do_that();
bind1st
i bind2nd
są przestarzałe od C ++ 11 i całkowicie usunięte w C ++ 17. Zamiast tego używaj bind
z placeholders
i / lub lambdas.
Oto funkcja, która będzie działać dla każdego kontenera:
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();
}
Pamiętaj, że możesz uciec z 1 parametrem szablonu, ponieważ możesz wyodrębnić go value_type
z kontenera. Potrzebujesz, typename
ponieważ ponieważ Container::value_type
jest to nazwa zależna .
Pamiętaj, że jeśli będziesz przeprowadzać wiele przeglądów, lepiej nadają się pojemniki STL. Nie wiem, jaka jest twoja aplikacja, ale warto rozważyć kontenery asocjacyjne, takie jak std :: map.
std :: vector jest pojemnikiem z wyboru, chyba że masz powód innego, a wyszukiwania według wartości mogą być takim powodem.
Użyj funkcji wyszukiwania STL .
Należy pamiętać, że istnieje również funkcja find_if , z której można skorzystać, jeśli wyszukiwanie jest bardziej złożone, tj. Jeśli nie szukasz tylko elementu, ale na przykład chcesz sprawdzić, czy element spełnia określony warunek, na przykład ciąg rozpoczynający się od „abc”. ( find_if
dałby ci iterator, który wskazuje na pierwszy taki element).
Dzięki doładowaniu możesz użyć any_of_equal
:
#include <boost/algorithm/cxx11/any_of.hpp>
bool item_present = boost::algorithm::any_of_equal(vector, element);
Możesz wypróbować ten kod:
#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()
}
Możesz użyć find
funkcji znajdującej się w std
przestrzeni nazw, tj std::find
. Przekazujesz std::find
funkcję begin
i end
iterator z wektora, który chcesz wyszukać, wraz z szukanym elementem i porównujesz wynikowy iterator z końcem wektora, aby sprawdzić, czy są one zgodne.
std::find(vector.begin(), vector.end(), item) != vector.end()
Możesz także wyłuskać ten iterator i używać go normalnie, jak każdego innego iteratora.
Możesz też użyć count. Zwróci liczbę elementów obecnych w wektorze.
int t=count(vec.begin(),vec.end(),item);
find
jest szybszy niż count
, ponieważ nie liczy się po pierwszym meczu.
Kolejny przykład wykorzystujący operatory 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 i wyżej):
można std::search
również użyć
Jest to również przydatne do wyszukiwania sekwencji elementów.
#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;
}
Istnieje również elastyczność przekazywania niektórych algorytmów wyszukiwania. Zobacz tutaj.
Ostatnio osobiście używałem szablonów do obsługi wielu rodzajów pojemników jednocześnie, zamiast zajmować się tylko wektorami. Znalazłem podobny przykład online (nie pamiętam, gdzie), więc uznanie należy się każdemu, z kogo go ukradłem. Ten szczególny wzór wydaje się również obsługiwać surowe tablice.
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);
}
Korzystanie z Newton C ++ jest łatwiejsze, samo-udokumentowane i szybsze niż w przypadku std :: find, ponieważ zwraca bool bezpośrednio.
bool exists_linear( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )
bool exists_binary( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )
Myślę, że to oczywiste, co robią te funkcje.
include <newton/algorithm/algorithm.hpp>
if ( newton::exists_linear(first, last, value) )
do_this();
else
do_that();