Sign in to follow this  
toddhd

One more question on std::find(), vectors and struct

Recommended Posts

I'd like to know if this can be done: Please consider the following: struct Record { string FirstName; string LastName; string Title; } std::vector<Record> People; Ok, I won't go through all the code, but lets assume that People gets loaded up with several Records. Now, lets assume that I want to search for a Record by LastName. Let's say the last name of the person is Smith. If we were dealing with a vector<string>, the find() might look like this: vector<string>::iterator iter = find(content.begin(), content.end(), "Smith"); But since we are dealing with a struct (Record), I need a way to instruct find() to search Record.LastName only. How can I do this?

Share this post


Link to post
Share on other sites
You want std::find_if, not std::find; the former allows you to define and provide a suitable predicate for comparison. See here for details. (Alternatively you could, of course, define operator== for your struct in a suitable fashion—but you may not always want to tie your equivalence semantics to surname only.)

Share this post


Link to post
Share on other sites

#include <functional>

struct RecordLastNameIs
: std::unary_function<Record, bool>
{
std::string name_;

RecordLastNameIs(const std::string& name)
: name_(name)
{}

bool operator()( const Record& rec ) const
{
return rec.LastName == name_;
}
};

std::find_if(People.begin(),
People.end(),
RecordLastNameIs("Smith"));





You may get away with making name_ a reference, depending on how you're going to use the function object.

Share this post


Link to post
Share on other sites
Quote:
Original post by Miserable
Alternatively you could, of course, define operator== for your struct in a suitable fashion—but you may not always want to tie your equivalence semantics to surname only.


Or you could define operator== for your struct as taking a string in the form "key=value", then use string.find('=') to separate the string into key and value, and then test the field name "key" against "value".
This may incur noticeable overhead, but it is extremely flexible (I believe this approach is know as key-value coding, and usually has get() and set() functions working the same way).

SwiftCoder

Share this post


Link to post
Share on other sites
And I believe you can also do it like this (with boost::lambda)

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

using namespace boost::lambda;

std::find_if( People.begin(), People.end(),
bind(&Record::LastName, _1) == "Smith" );

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this