std :: find成员查找对象

时间:2013-05-08 16:12:41

标签: c++ stl find member

方案

我在使用STL的时候遇到了一个速度突发,看起来像是一个正常的场景,简化了这里:

class Person {
  string Name;
  int    Age;
};

vector<Person> people;
AddPeople(people);

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


问题

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


问题

是否有更好或更合适的方式来实现“STL方式”?建议的问题没有帮助,但我设法找到了几个related questions但没有直接解决方案。


<小时/>

的变通/测试

有一些潜在的解决方法:

  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()
    
  5. 看起来#4是最好的候选人,但似乎没有理想或感觉“STL”,有些人有问题。

3 个答案:

答案 0 :(得分:5)

  

有没有更好或更合适的方法来实现“STL方式”?

您可以使用std::find_if(由C ++ 11 lambdas提供支持):

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 ++标准库的容器和算法库的强大灵感,但两者并不相同。有关详细信息,请参阅this Q&A on StackOverflow

修改

由于您使用的是不支持lambdas的编译器,因此您可以定义自己的仿函数谓词:

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

答案 1 :(得分:1)

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

第一种是使用新的C ++ 11 lambda:

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

如果你有一个不支持lambdas的旧编译器,你可以使用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"));

当然,这两个都要求您的班级公开Name成员。但您可以将其更改为使用公共GetName函数,并将其添加到类中。

答案 2 :(得分:1)

我想你想要这些用于子类或共享名为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;
}

或者您希望搜索功能正常工作,希望这有助于您