按对象属性搜索对象矢量

Chr*_*fer 34 c++ gcc stl std

我试图找出一种很好的方法来找到向量中某个对象的索引 - 通过将字符串与对象中的成员字段进行比较.

find(vector.begin(), vector.end(), [object where obj.getName() == myString])
Run Code Online (Sandbox Code Playgroud)

我搜索没有成功 - 也许我不完全明白要寻找什么.

jua*_*nza 54

您可以使用std::find_if合适的仿函数.在此示例中,使用了C++ 11 lambda:

std::vector<Type> v = ....;
std::string myString = ....;
auto it = find_if(v.begin(), v.end(), [&myString](const Type& obj) {return obj.getName() == myString;})

if (it != v.end())
{
  // found element. it is an iterator to the first matching element.
  // if you really need the index, you can also get it:
  auto index = std::distance(v.begin(), it);
}
Run Code Online (Sandbox Code Playgroud)

如果你没有C++ 11 lambda支持,那么一个函子可以工作:

struct MatchString
{
 MatchString(const std::string& s) : s_(s) {}
 bool operator()(const Type& obj) const
 {
   return obj.getName() == s_;
 }
 private:
   const std::string& s_;
};
Run Code Online (Sandbox Code Playgroud)

MatchString是一个类型,其实例可以使用单个Type对象调用,并返回一个布尔值.例如,

Type t("Foo"); // assume this means t.getName() is "Foo"
MatchString m("Foo");
bool b = m(t); // b is true
Run Code Online (Sandbox Code Playgroud)

然后你可以传递一个实例 std::find

std::vector<Type>::iterator it = find_if(v.begin(), v.end(), MatchString(myString));
Run Code Online (Sandbox Code Playgroud)


Arn*_*rtz 6

除了juancho使用的Lambda和手写函子之外,你还可以使用boost::bind(C++ 03)或std::bind(C++ 11)和一个简单的函数:

bool isNameOfObj(const std::string& s, const Type& obj)
{ return obj.getName() == s; }

//...
std::vector<Type>::iterator it = find_if(v.begin(), v.end(), 
  boost::bind(&isNameOfObj, myString, boost::placeholders::_1));
Run Code Online (Sandbox Code Playgroud)

或者,如果Type有方法isName:

std::vector<Type>::iterator it = find_if(v.begin(), v.end(), 
  boost::bind(&Type::isName, boost::placeholders::_1, myString));
Run Code Online (Sandbox Code Playgroud)

这只是为了完整性.在C++ 11中,我更喜欢Lambdas,在C++ 03中,如果比较函数本身已经存在,我只会使用bind.如果没有,请选择仿函数.

PS:由于C++ 11没有多态/模板化lambda,因此bind仍然在C++ 11中占有一席之地,例如,如果参数类型未知,难以拼写,或者不易推断.