web-dev-qa-db-ja.com

オブジェクト属性によるオブジェクトのベクトルの検索

文字列をオブジェクトのメンバーフィールドと比較することで、ベクター内の特定のオブジェクトのインデックスを見つける素敵な方法を見つけようとしています。

このような:

find(vector.begin(), vector.end(), [object where obj.getName() == myString])

私は成功せずに検索しました-何を探すべきかを完全に理解していないかもしれません。

32
Christoffer

適切なファンクターとともに std::find_if を使用できます。この例では、C++ 11ラムダが使用されます。

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

C++ 11ラムダサポートがない場合は、ファンクターが機能します。

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

ここで、MatchStringは、インスタンスが単一のTypeオブジェクトで呼び出し可能なタイプであり、ブール値を返します。例えば、

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

その後、std::findにインスタンスを渡すことができます

std::vector<Type>::iterator it = find_if(v.begin(), v.end(), MatchString(myString));
53
juanchopanza

ラムダとjuanchoで使用される手書きファンクターに加えて、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));

または、TypeにメソッドisNameがある場合:

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

これは完全を期すためのものです。 C++ 11ではLambdasを、C++ 03では比較関数自体が既に存在する場合にのみバインドを使用します。そうでない場合は、ファンクターを優先します。

PS: C++ 11にはポリモーフィック/テンプレート化されたラムダがないため、bindはC++ 11での位置を保持しています。パラメータの種類が不明な場合、綴りが難しい場合、または推測が容易でない場合。

6
Arne Mertz

単純なイテレータが役立つ場合があります。

typedef std::vector<MyDataType> MyDataTypeList;
// MyDataType findIt should have been defined and assigned 
MyDataTypeList m_MyObjects;
//By this time, the Push_back() calls should have happened
MyDataTypeList::iterator itr = m_MyObjects.begin();
while (itr != m_MyObjects.end())
{
  if(m_MyObjects[*itr] == findIt) // any other comparator you may want to use
    // do what ever you like
}
3
uniqrish