的std ::会员找到对象(std::find Object by Member)

2019-09-02 06:22发布

脚本

我一直在使用什么看起来像一个正常的情况下,这里简化了STL碰上speedbump:

class Person {
  string Name;
  int    Age;
};

vector<Person> people;
AddPeople(people);

string s("Bob");
find(people.begin(), people.end(), s);


问题

不幸的是find需要比较整个班级。


有没有更好或更合适的方式来做到这一点,“STL的方式”? 建议的提问是没有帮助的,但我设法找到了几个相关的 问题,但没有直接的解决方案。



变通/测试

这里也有一些潜在的变通办法:

  1. 放弃find共(凌乱,但可以重构):

     bool bBob = false; for (UINT i = 0; i < people.size(); i++) { if (people[i].Name == s) bBob = true; break; } 
  2. 提供转换操作符(隐式转换不工作;明确不能使用find ):

     class Person { string Name; int Age; operator string() {return Name;} }; Person b ("Bob", 99); string s ("Bob"); b == s; //doesn't work string(b) == s; //works, but no good for find() 
  3. 定义一个独立平等的运营商(简单,有效,而且在全球曝光):

     BOOL operator==(Person l, string r) { return l.Name == r; } 
  4. 限定构件相等操作(使得比较顺序依赖性的;对象必须是第一个):

     class Person { string Name; int Age; bool operator==(string s) {return Name == s;} }; Person b ("Bob", 99); string s ("Bob"); b==s; //works s==b; //doesn't work, but not a problem for find() 

它看起来像#4是最佳人选,但似乎没有一个理想的或感觉“STL”,以及一些有问题。

Answer 1:

有没有更好或更合适的方式来做到这一点,“STL的方式”?

您可以使用std::find_if (搭载C ++ 11个lambda表达式):

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

请注意,这称之为“STL办法”是不合适的。 这是C ++标准库,而不是STL(“标准模板库”)。 STL中充当了C ++标准库的容器和算法库强大的灵感,但两件事情是不一样的。 见这个Q&A在计算器上获得更多信息。

编辑:

由于您使用的是不支持lambda表达式编译器,你可以定义自己的仿函数谓词:

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;
};

并与使用它std::find_if这样:

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


Answer 2:

有几个方法可以做到这一点,所有涉及某种可调用的对象和std::find_if

第一种方法是使用新的C ++ 11拉姆达:

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

如果你有一个旧的编译器不支持lambda表达式,你可以使用一个仿函数对象 :

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"));

当然,这两个需要你的类有Name的成员public。 但你可以改变它使用一个公共GetName函数,然后添加到类。



Answer 3:

我猜你想让这些子类或共享一个名为name属性类,如果不是你可以自己创建一个简单的函数。 如果你希望它为有您可以创建这样的一个模板的属性名称的任何类工作:

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;
}

不过还是要工作的搜索功能,希望这可以帮助你



文章来源: std::find Object by Member