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

Поиск элемента struct в векторе по данным участника

Я очень новичок в С++, и я пытаюсь найти способ поиска вектора structs для структуры с определенными данными элемента.

Я знаю, что это будет работать с простыми типами в векторе

std::find(vector.begin(), vector.end(), item) != vector.end()

Но скажем, у меня есть такая структура:

struct Friend
{
  string name;
  string number;
  string ID;
};

и такой вектор:

vector<Friend> friends;

Затем вектор заполняется друзьями.

Скажем, я хочу найти друга с определенным идентификатором, а также подробности. Или удалите определенную структуру из вектора. Есть ли простой способ сделать это?

4b9b3361

Ответ 1

Это можно сделать с помощью std::find_if и предиката поиска, который может быть выражен как лямбда-функция, если у вас есть С++ 11 (или С++ 0x):

auto pred = [](const Friend & item) {
    return item.ID == 42;
};
std::find_if(std::begin(friends), std::end(friends), pred) != std::end(friends);

Чтобы использовать идентификатор, заданный как переменную, вы должны записать его в выражении лямбда (в [...]):

auto pred = [id](const Friend & item) {
    return item.ID == id;
};
std::find_if(std::begin(friends), std::end(friends), pred) != std::end(friends);

Если у вас нет С++ 11, вам нужно определить предикат как функтор (объект функции). Ответ Remy Lebeau использует этот подход.

Чтобы удалить элементы, соответствующие критериям, определенным предикатом, используйте remove_if вместо find_if (остальная часть синтаксиса одинаков).

Дополнительные алгоритмы см. в ссылка STL <algorithm>.

Ответ 2

Используйте std::find_if(). @leemes и @AndyProwl показали вам, как использовать его в компиляторе С++ 11. Но если вы не используете компилятор С++ 11, вместо этого вы можете использовать его так, чтобы он определял функтор, сравнивающий идентификатор данного элемента с ранее указанным ID в его конструкторе:

class MatchesID
{
    std::string _ID;

public:
    MatchesID(const std::string &ID) : _ID(ID) {}

    bool operator()(const Friend &item) const
    {
        return item.ID == _ID;
    }
};

std::find_if(vector.begin(), vector.end(), MatchesID("TheIDHere")) != vector.end();

Если у вас есть другие классы в вашем проекте, в которых используются идентификаторы, вы можете сделать этот шаблонный шаблон:

template<typename IDType>
class MatchesID
{
    IDType _ID;

public:
    MatchesID(const IDType &ID) : _ID(ID) {}

    template<class ItemType>
    bool operator()(const ItemType &item) const
    {
        return item.ID == _ID;
    }
};

std::find_if(vector.begin(), vector.end(), MatchesID<std::string>("TheIDHere")) != vector.end();

Ответ 3

Вы можете использовать std::find_if в комбинации с функторами (если вы работаете с С++ 98) или lambdas (если вы используете С++ 11, который я буду предполагать):

using namespace std;
int ID = 3; // Let say...
auto it = find_if(begin(vector), end(vector), [=] (Friend const& f) { 
    return (f.ID == ID); 
    });
bool found = (it != end(vector));

Ответ 4

Если вы хотите найти элемент в контейнере STL, используйте std:: find или std:: find_if алгоритмы С С++ 03 вам нужно перегрузить operator == для std:: find

bool operator==(const Friend& lhs, const Friend& rhs)
{
  return lhs.ID == rhs.ID;
}

if (std::find(friends.begin(), friends.end(), item) != friends.end())
{
   // find your friend
}

ИЛИ С++ 11 с lambda:

std::find_if(friends.begin(), friends.end(),  [](Friend& f){ return f.ID == "1"; } );

Если вы хотите удалить определенный элемент, используйте std:: remove_if

std::remove_if(friends.begin(), friends.end(), 
      [](Friend& f){ return f.ID == "1"; });