Поиск С++ стандартного вектора структур для структуры с соответствующей строкой

Я уверен, что делаю это сложнее, чем нужно.

У меня есть вектор...

vector<Joints> mJointsVector;

...состоит из структур по образцу следующего:

struct Joints
{
    string name;

    float origUpperLimit;
    float origLowerLimit;   
};

Я пытаюсь выполнить поиск mJointsVector с помощью "std::find", чтобы найти отдельный сустав по его строковому имени - пока безуспешно, но примеры из следующих помогли, по крайней мере, концептуально:

Векторы, структуры и std::find

Может ли кто-нибудь указать мне дальше в правильном направлении?


person Monte Hurd    schedule 08.01.2010    source источник
comment
Хотя приведенные ниже ответы хороши, ваше использование звучит так, как будто вместо этого вы должны использовать map, от string до Joints. Это также улучшит время поиска.   -  person GManNickG    schedule 08.01.2010
comment
Я думаю, что вы, вероятно, правы - мне придется изучить это позже.   -  person Monte Hurd    schedule 08.01.2010
comment
Вау, карты и мультикарты прекрасны! Особенно с for_each, использующим функциональные объекты вместо циклов! codeproject.com/KB/stl/replace_for_for_each.aspx?display=Print Так полезно иметь возможность повторно использовать код цикла таким образом.   -  person Monte Hurd    schedule 09.02.2010


Ответы (4)


Прямой подход:

struct FindByName {
    const std::string name;
    FindByName(const std::string& name) : name(name) {}
    bool operator()(const Joints& j) const { 
        return j.name == name; 
    }
};

std::vector<Joints>::iterator it = std::find_if(m_jointsVector.begin(),
                                                m_jointsVector.end(),
                                                FindByName("foo"));

if(it != m_jointsVector.end()) {
    // ...
}

В качестве альтернативы вы можете изучить что-то вроде Boost.Bind чтобы уменьшить количество кода.

person Georg Fritzsche    schedule 08.01.2010
comment
хотя это работает, я думаю, что оператор() объекта функции всегда должен быть константным, просто для гибкости. если однажды у вас будет диапазон const Joints, объект функции все еще будет работать. - person vividos; 08.01.2010
comment
Кажется, это работает только в том случае, если я изменяю bool operator( на bool operator()(. Это правильно? Я поражен тем, сколько существует способов сделать это! - person Monte Hurd; 08.01.2010
comment
Ой, я пропустил первые скобки - исправлено. - person Georg Fritzsche; 08.01.2010
comment
@vividos: Это уже работает с const Joints - хотя я согласен с константностью. - person Georg Fritzsche; 08.01.2010

как насчет:

std::string name = "xxx";

std::find_if(mJointsVector.begin(), 
             mJointsVector.end(), 
             [&s = name](const Joints& j) -> bool { return s == j.name; }); 
person Community    schedule 08.01.2010
comment
Что? Это еще не поддерживается: P (даже тогда я думаю, что это неправильно.) - person GManNickG; 08.01.2010
comment
Это не неправильно, это правильно, и через пару лет этот ответ будет считаться более правильным по сравнению с другими. - person ; 08.01.2010
comment
Дарид, что ты имеешь в виду? Почему это правильнее? Я не бросаю вам вызов — на самом деле я совершенно невежественен — и мне любопытно. - person Monte Hurd; 08.01.2010
comment
@darid: Не редактируйте свой ответ, затем опровергните мое утверждение! :P Это как виртуальный соломенный человек. Это было неправильно, но теперь это определенно хорошо. :] - person GManNickG; 08.01.2010
comment
@Monte: другие ответы - это то, что вам нужно сделать сегодня. Эта функция, называемая лямбда-выражениями, в основном представляет собой встроенные функции. По сути, они создают безымянные функторы, аналогичные другим ответам. Но это сохраняет логику ближе к вызывающему сайту и, возможно, более читабельно. - person GManNickG; 08.01.2010
comment
Хотя анонимная функция — хорошая идея, не следует ли вам использовать find_if? - person xtofl; 08.01.2010
comment
Он поддерживается компиляторами Intel (лямбды, я не тестировал этот) и кажется неправильным: аргумент должен быть const Joint& и сравнение должно быть, вероятно, name != s.name, а должно быть find_if - person David Rodríguez - dribeas; 08.01.2010
comment
@GMan: боже, ты слишком быстр для меня, я надеялся остаться незамеченным с этим редактированием :› - person ; 08.01.2010
comment
@dribeas: (1) Тип — Joints, а не Joint (2) Сравнение правильное — пожалуйста, прочитайте код (3) Обычно это направление, в котором движется C++, люди должны начать использовать эти функции вместо того, чтобы разбрасываться с vc6, vc8 , компиляторы vc9 поколения. - person ; 08.01.2010
comment
Значит, поддержка лямбда не вездесуща? Может ли кто-нибудь сказать мне, безопасно ли их использовать с проектами OS X 10.6 или iPhone? - person Monte Hurd; 08.01.2010
comment
Я пропустил ваш отредактированный код, читая некоторые другие ответы, так что вы правы как в суставах, так и в правильном сравнении. Тем не менее это должно быть find_if вместо find, и я не уверен, что синтаксис, который вы используете для захвата переменной name, верен. Может быть: std::find_if(...,[&name](const Joints& j)->...)? - person David Rodríguez - dribeas; 08.01.2010
comment
@Monte: это функция, которая будет в следующем стандарте C++, который еще не вышел. Текущие версии gcc поддерживают это при установке флага, Visual Studio 2010 также будет их поддерживать. - person Georg Fritzsche; 08.01.2010
comment
@Monte: если вы можете использовать g++ 4.5 или более позднюю версию, вы можете попробовать, но в g++ 4.4 и более ранних версиях не было поддержки лямбда. И опять же, я бы не стал пробовать последнее дополнение к компилятору для производственного кода, пока не будет проведено какое-то время и не будет проведено тестирование. - person David Rodríguez - dribeas; 08.01.2010

Вы должны иметь возможность добавить оператор равенства в свою структуру

struct Joints
{
    std::string name;

    bool operator==(const std::string & str) { return name == str; }
};

Затем вы можете искать с помощью find.

person Jason T.    schedule 08.01.2010
comment
Оператор равенства следует зарезервировать для проверки эквивалентности двух объектов одного типа. Только очень редко вы должны использовать его для сравнения с другими типами. - person Martin York; 08.01.2010
comment
Не могли бы объяснить, почему, или процитировать источник, который это делает? - person Jason T.; 08.01.2010
comment
Этот простой короткий ответ имеет много недостатков: вы должны предпочесть свободные операторы функций операторам функций-членов (симметрия по отношению к типам в некоторых операциях), если вы перегружаете ==, вы также должны перегружать !=, и, наконец, как указал Мартин, при перегрузке оператора вы не должны менять семантику. Символ оператора подразумевает для читателя некоторую семантику, и если эта семантика нарушена, вероятность ошибок в пользовательском коде возрастает. Кто мог подумать, что a==b будет истинным для разных объектов? - person David Rodríguez - dribeas; 08.01.2010

person    schedule
comment
Вы никогда не объявляли _currString или _findString, и ваше наследование неверно (уточните параметры шаблона) - person Matthieu M.; 08.01.2010