I'm very new to c++ and I'm trying to find a way to search a vector of structs for a struct with a certain member data.
I know this would work with simple types in the vector
std::find(vector.begin(), vector.end(), item) != vector.end()
But lets say I have a struct like this:
struct Friend
{
string name;
string number;
string ID;
};
and a vector like this:
vector<Friend> friends;
Then the vector is filled with friends.
Let's say I want to search for a friend with a certain ID, and cout the details. Or delete the certain struct from the vector. Is there a simple way to do this?
This can be done with std::find_if
and a search predicate, which can be expressed as a lambda function if you have C++11 (or C++0x) available:
auto pred = [](const Friend & item) {
return item.ID == 42;
};
std::find_if(std::begin(friends), std::end(friends), pred) != std::end(friends);
To use an ID given as a variable, you have to capture it in the lambda expression (within the [...]
):
auto pred = [id](const Friend & item) {
return item.ID == id;
};
std::find_if(std::begin(friends), std::end(friends), pred) != std::end(friends);
If you don't have C++11 available, you have to define the predicate as a functor (function object). Remy Lebeau's answer uses this approach.
To remove elements matching the criteria as defined by the predicate, use remove_if
instead of find_if
(the rest of the syntax is the same).
For more algorithms, see the STL <algorithm>
reference.
Use std::find_if()
. @leemes and @AndyProwl showed you how to use it in a C++11 compiler. But if you are not using a C++11 compiler, then you can use it like this instead, which defines a functor comparing the ID of a given item with a previously specified ID in its constructor:
class MatchesID
{
std::string _ID;
public:
MatchesID(const std::string &ID) : _ID(ID) {}
bool operator()(const Friend &item) const
{
return item.ID == _ID;
}
};
std::find_if(vector.begin(), vector.end(), MatchesID("TheIDHere")) != vector.end();
If you have other classes in your project which use IDs, you can make this functor templated:
template<typename IDType>
class MatchesID
{
IDType _ID;
public:
MatchesID(const IDType &ID) : _ID(ID) {}
template<class ItemType>
bool operator()(const ItemType &item) const
{
return item.ID == _ID;
}
};
std::find_if(vector.begin(), vector.end(), MatchesID<std::string>("TheIDHere")) != vector.end();
You can use std::find_if
in combination with functors (if you are working with C++98) or lambdas (if you are using C++11, which I will assume):
using namespace std;
int ID = 3; // Let's say...
auto it = find_if(begin(vector), end(vector), [=] (Friend const& f) {
return (f.ID == ID);
});
bool found = (it != end(vector));
If you want to find an element in STL container, use std::find or std::find_if algorithms With C++03, you need to overload operator== for std::find
bool operator==(const Friend& lhs, const Friend& rhs)
{
return lhs.ID == rhs.ID;
}
if (std::find(friends.begin(), friends.end(), item) != friends.end())
{
// find your friend
}
OR C++11 with lambda:
std::find_if(friends.begin(), friends.end(), [](Friend& f){ return f.ID == "1"; } );
If you want to remove a certain element, use std::remove_if
std::remove_if(friends.begin(), friends.end(),
[](Friend& f){ return f.ID == "1"; });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With