Подтвердить что ты не робот

Поиск объекта объектов по атрибуту объекта

Я пытаюсь найти хороший способ найти индекс определенного объекта в векторе - сравнивая строку с полем члена в объекте.

Как это:

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

Я безуспешно искал - может быть, я не совсем понимаю, что искать.

4b9b3361

Ответ 1

Вы можете использовать std::find_if с подходящим функтором. В этом примере используется lambda С++ 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);
}

Если у вас нет поддержки lambda С++ 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));

Ответ 2

В дополнение к Lambda и рукописному функтору, используемому juancho, у вас есть возможность использовать boost::bind (С++ 03) или std::bind (С++ 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));

Это просто для полноты. В С++ 11 я бы предпочел Lambdas, в С++ 03 я бы использовал bind, только если сама функция сравнения уже существует. Если нет, предпочтите функтор.

PS: Поскольку С++ 11 не имеет полиморфных/шаблонных lambdas, bind все еще имеет место в С++ 11, например. если типы параметров неизвестны, трудно записать или иначе нелегко вывести.

Ответ 3

Простой итератор может помочь.

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
}