2013-03-20 33 views
19

Bir vektördeki belirli bir nesnenin dizinini bulmanın güzel bir yolunu bulmaya çalışıyorum - bir dizeyi nesne içindeki bir üye alanıyla karşılaştırarak.Nesnelerin nesnesine göre nesne özniteliğine göre ara

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

Başarı olmadan arama yaptım - belki de tam olarak neyi arayacağımı anlamıyorum.

+1

Aynı ada sahip birden fazla nesne olabilir mi? Hepsini bulmak ister misin? –

cevap

36

std::find_if'u uygun bir functor ile kullanabilirsiniz. Bu örnekte, bir C++ 11 lambda kullanılır: Eğer hiçbir C++ 11 lambda desteği varsa

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

, bir funktor çalışacak: Burada

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 olan bir türüdür örnekler tek bir Type nesnesiyle çağrılabilir ve bir boole döndürür. Örneğin,

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

sonra Lambda ve Juancho tarafından kullanılan el yazısı funktor ek olarak std::find

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

Bir functor kullanıyorsanız 'find_if 'öğesini kullanmanız gerekir. – Peter

+0

@Peter iyi yakalama, teşekkürler! – juanchopanza

5

için bir örneği geçebilir Eğer boost::bind (C++ 03 kullanma olanağı,) ya da std::bind (C++ 11) ve basit bir fonksiyonu: Type bir yöntem isName varsa

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

veya:

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

Bu yalnızca tamlık içindir. C++ 11'de Lambdas'ı tercih ederim, C++ 03'te sadece karşılaştırma fonksiyonu zaten mevcutsa bağlayıcı kullanırdım. Değilse, functor'ı tercih edin.

PS: C++ 11'in bir polimorfik/templated lambda'sı olmadığı için, bağlama hala C++ 11'de yer almaktadır, örn. Parametre türleri bilinmiyorsa, yazım zor veya başka bir şekilde çıkarılması kolay değilse.

2

Basit bir yineleyici yardımcı olabilir.

İlgili konular