All I want to do is to check whether an element exists in the vector or not, so I can deal with each case.
if ( item_present )
do_this();
else
do_that();
All I want to do is to check whether an element exists in the vector or not, so I can deal with each case.
if ( item_present )
do_this();
else
do_that();
You can use std::find
from <algorithm>
:
#include <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()
This returns an iterator to the first element found. If not present, it returns an iterator to one-past-the-end. With your example:
#include <algorithm>
#include <vector>
if ( std::find(vec.begin(), vec.end(), item) != vec.end() )
do_this();
else
do_that();
#include <algorithm>
or else you might get very strange errors like 'can't find matching function in namespace std' –
Retool bool
. It's a drop in replacement (or initialization) of item_present
in the original question. –
Interlocution .find()
is still not a member function of std::vector
, as you'd expect it should be? I wonder if this is somehow a consequence of templating. –
Poem std::vector<>::find()
would not give any advantage, nor is it needed, therefore, no, it should not be a member. See also en.wikipedia.org/wiki/Coupling_%28computer_programming%29 –
Insertion vector.end()
once before realizing that, first, if I'm really concerned with speed, I shouldn't be using find()
on a vector at all, and second, that vector.end()
being called once instead of twice is hardly any improvement at all. –
Byandby vector
will often be far quicker to search than a map
or set
. –
Melodist end() call is inlined by the compiler so there's no actual
call` at all but just a raw pointer. –
Aristotle find
should not be added as a member to std::vector
; whether existing members make sense or not was not discussed, and indeed the STL is not well designed in many aspects, mainly because the lack of experience (and my post was a response to bobobobo, who implied that members are part of the OOP concept, but they are not) –
Insertion mvec.find(key) != mvec.cend()
is preferable to std::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend()
. –
Moersch #include
the <algorithm>
header when using std::find
has even gotten worse: error: cannot bind non-const lvalue reference of type ‘__gnu_cxx::__normal_iterator<const int*, std::vector<int> >&’ to an rvalue of type ‘__gnu_cxx::__normal_iterator<const int*, std::vector<int> >’
–
Quiz mvec.find(mvec.cbegin(), mvec.cend(), key) != mvec.cend()
which isn't a particularly cleaner interface than the nonmember function. –
Subadar std::vector::find()
is not implemented, as it is not better than std::find()
. The problem is, that a programmer, that upgrades a certain data structure from std::vector
to std::multiset
(or std::set
) then has to walk through the code and update every place, where a find()
is performed. It would be nice, if the APIs of std::(multi)set
and std::vector
would be as similiar as possible. –
Quiz std::vector<std::shared_ptr...>
and other pimpl expressions. Does anyone know how to make it work?? –
Lazulite vector
) should mimic the concept of containers in the real world. The fact that I have to say what type of objects a container can hold (the template parameter) doesn't match the real world, where containers can hold anything provided there's enough space. And since finding things in containers is a common thing to do, it should be part of the container interface. –
Mathew As others have said, use the STL find
or find_if
functions. But if you are searching in very large vectors and this impacts performance, you may want to sort your vector and then use the binary_search
, lower_bound
, or upper_bound
algorithms.
std::set<>
together with find()
indeed. Or use std::map<>
depending on your needs. –
Polack If your vector is not ordered, use the approach MSN suggested:
if(std::find(vector.begin(), vector.end(), item)!=vector.end()){
// Found the item
}
If your vector is ordered, use binary_search method Brian Neal suggested:
if(binary_search(vector.begin(), vector.end(), item)){
// Found the item
}
binary search yields O(log n) worst-case performance, which is way more efficient than the first approach. In order to use binary search, you may use qsort to sort the vector first to guarantee it is ordered.
std::sort
? qsort
is very inefficient on vectors.... see: #12308743 –
Nertie Use find from the algorithm header of stl.I've illustrated its use with int type. You can use any type you like as long as you can compare for equality (overload == if you need to for your custom class).
#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;
}
In C++11 you can use any_of
. For example if it is a vector<string> v;
then:
if (any_of(v.begin(), v.end(), bind(equal_to<string>(), _1, item)))
do_this();
else
do_that();
Alternatively, use a lambda:
if (any_of(v.begin(), v.end(), [&](const std::string& elem) { return elem == item; }))
do_this();
else
do_that();
bind1st
and bind2nd
are deprecated since C++11 and completely removed in C++17. Use bind
with placeholders
and/or lambdas instead. –
Unilateral std::any_of()
when we have std::find()
? –
Aurea std::find()
when we have std::any_of
? –
Delgadillo I use something like this...
#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
...as that way it's actually clear and readable. (Obviously you can reuse the template in multiple places).
value_type
from the container for the element type. I've added an answer like this. –
Grattan if true return true else return false
. The method can be one lined in : return std::find(Vec.begin(), Vec.end(), Element) != Vec.end();
–
Nevins Here's a function that will work for any Container:
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();
}
Note that you can get away with 1 template parameter because you can extract the value_type
from the Container. You need the typename
because Container::value_type
is a dependent name.
ranges
, so that could just be called Range
rather than Container
, and Bob's your uncle. –
Ericaericaceous From C++20, using ranges (#include <ranges>
)
//SAMPLE DATA
std::vector<int> vecOfElements = { 2,4,6,8 };
//DO SOMETHING IF 8 IN VECTOR
if (std::ranges::find(vecOfElements, 8) != vecOfElements.end())
{
std::cout << "DO SOMETHING" << std::endl;
}
Bear in mind that, if you're going to be doing a lot of lookups, there are STL containers that are better for that. I don't know what your application is, but associative containers like std::map may be worth considering.
std::vector is the container of choice unless you have a reason for another, and lookups by value can be such a reason.
With boost you can use any_of_equal
:
#include <boost/algorithm/cxx11/any_of.hpp>
bool item_present = boost::algorithm::any_of_equal(vector, element);
In C++23 we finally have the most obvious solution:
if (std::ranges::contains(vec, item))
do_this();
else
do_that();
Use the STL find function.
Keep in mind that there is also a find_if function, which you can use if your search is more complex, i.e. if you're not just looking for an element, but, for example, want see if there is an element that fulfills a certain condition, for example, a string that starts with "abc". (find_if
would give you an iterator that points to the first such element).
You can try this 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()
}
You can use the find
function, found in the std
namespace, ie std::find
. You pass the std::find
function the begin
and end
iterator from the vector you want to search, along with the element you're looking for and compare the resulting iterator to the end of the vector to see if they match or not.
std::find(vector.begin(), vector.end(), item) != vector.end()
You're also able to dereference that iterator and use it as normal, like any other iterator.
template <typename T> bool IsInVector(const T & what, const std::vector<T> & vec)
{
return std::find(vec.begin(),vec.end(),what)!=vec.end();
}
std::find()
to be usable with containers, do it generically rather than for just a vector. And maybe call it find()
or stdx::find()
or something. –
Aurea std::ranges::contains
. –
Bolivar You can use count too. It will return the number of items present in a vector.
int t=count(vec.begin(),vec.end(),item);
find
is faster than count
, because it doesn't keep on counting after the first match. –
Saberio I've personally used templates of late to handle multiple types of containers at once rather than deal only with vectors. I found a similar example online (can't remember where) so credit goes to whoever I've pilfered this from. This particular pattern seems to handle raw arrays as well.
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);
}
template <typename Container> struct value_type { ... etc. ... }
–
Aurea (C++17 and above):
can use std::search
also
This is also useful for searching sequence of elements.
#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;
}
Also there is flexibility of passing some search algorithms. Refer here.
If you wanna find a string in a vector:
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));
std::find
is just fine in this case, no need for the predicate object. –
Aurea Another way to do it is using std::count
.
Example code:
#include <algorithm>
#include <vector>
void run_vector_contains_example() {
std::vector<int> vec = {1, 2, 3, 4, 5};
int item_to_find = 3;
int count = std::count(vec.begin(), vec.end(), item_to_find);
if (count > 0) {
// item found in vector
} else {
// item not found in vector
}
}
Admittedly, this method might be slower than std::find
when dealing with large vectors.
© 2022 - 2024 — McMap. All rights reserved.
std::vector
, if it exists?" Or something like that. – Zettazeugma