std::find Object by Member

☆樱花仙子☆ 提交于 2019-11-29 15:09:26
Andy Prowl

Is there a better or more appropriate way to do this the “STL way”?

You can use std::find_if (powered by C++11 lambdas):

std::string name = "Bob";
// ...
std::find_if(std::begin(people), std::end(people), 
    [&] (Person const& p) { return p.Name == name; }

Notice, that calling it "STL way" is inappropriate. This is the C++ Standard Library, not the STL ("Standard Template Library"). The STL served as a strong inspiration for the Containers and Algorithms Library of the C++ Standard Library, but the two things are not the same. See this Q&A on StackOverflow for further information.

EDIT:

Since you are using a compiler that does not support lambdas, you can define your own functor predicate:

struct person_has_name
{
    person_has_name(std::string const& n) : name(n) { }  
    bool operator () (Person const& p) { return p.Name == name; }
private:
    std::string name;
};

And use it with std::find_if this way:

std::string name = "Bob";
// ...
std::find_if(people.begin(), people.end(), person_has_name(name));

There are a couple of ways to do it, all involving some kind of callable objects and std::find_if.

The first is to use the new C++11 lambda:

std::find_if(people.begin(), people.end(), [](const Person& person)
    { return person.Name == "Bob"; });

If you have an older compiler that doesn't support lambdas, you could use a functor object:

class FindPersonByName
{
    std::string name;

public:
    FindPersonByName(const std::string& name) : name(name) {}

    bool operator()(const Person& person) const
        { return person.Name == name; }
};

std::find_if(people.begin(), people.end(), FindPersonByName("Bob"));

Of course both of these requires your class to have the Name member public. But you can change it to use a public GetName function instead and add that to the class.

I guess you want these for subclasses or classes that share a property called name, if not you could create a simple function yourself. If you do want it to work for any class that has a property name you could create a template like this:

template < class ClassWithNameProperty >
ClassWithNameProperty * searchName (std::string name,
                                    std::vector<ClassWithNameProperty *> array)
{
    for (ClassWithNameProperty * obj: array)
    {
        if (obj.compare(obj->name))
        {
            return obj;
        }
    }
    return NULL;
}

Or however you want your search function to work, hope this helps you

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!