在c++中,如何通过给出对象的成员来查找对象向量中的某些项

In C++, how to find certain items in the vector of objects by giving the member of a object?

本文关键字:对象 查找 向量 成员 c++ 何通过      更新时间:2023-10-16

例如,我定义了类foo和向量vec:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class foo {
public:
    foo(int flag, char ch):flag(flag), ch(ch) {}
    int flag;
    char ch;
};
int main(void)
{
    vector<foo> vec;
    vec.push_back(foo(1,'a'));
    vec.push_back(foo(2,'b'));
    vec.push_back(foo(3,'c'));
    //blabla...
}

我已经找到了如何找到单个元素:如何在std::vector中找到一个项目?
但现在我想通过一个字符来找到一个对象,比如b。我怎样才能有效地实现这个目标?

您可以使用std::find_if:

 //c++14
 std::find_if(std::begin(vec),std::end(vec),
              [](auto&& v) { return v.ch == 'b'; })
 //c++11
 std::find_if(std::begin(vec),std::end(vec),
              [](const foo& v) { return v.ch == 'b'; })

如果您发现自己多次需要此模式,则可以将其封装在函数中:

//c++14, c++11 version left as exercise
decltype(auto) find_foo (const std::vector<foo>& vec, char c)
{
    return std::find_if(std::begin(vec),std::end(vec),
                        [c](auto&& v) { return v.ch == c; });
}

一个更好的选择可能是使用std::unordered_map<char,int>而不是std::vector<foo>:

int main()
{
    std::unordered_map<char,int> my_map;
    my_map['a'] = 1;
    my_map['b'] = 2;
    my_map['c'] = 3;
    cout << my_map['b']; //instead of that std::find_if nonsense
}

您可以使用标头<algorithm>中声明的标准算法std::find_if。例如

#include <iostream>
#include <algorithm>
class foo {
public:
    foo(int flag, char ch):flag(flag), ch(ch) {}
    int flag;
    char ch;
};
int main()
{
    std::vector<foo> vec;
    vec.push_back(foo(1,'a'));
    vec.push_back(foo(2,'b'));
    vec.push_back(foo(3,'c'));
    char ch = 'b';
    auto it = std::find_if( vec.begin(), vec.end(), 
                            [&]( const foo &f ) { return f.ch == ch; } );
    if ( it != vec.end() ) std::cout << it->flag << ' ' << it->ch << std::endl;
}    

如果你的编译器支持c++ 14,那么lambda表达式也可以这样写

auto it = std::find_if( vec.begin(), vec.end(), 
                        [ch = 'b']( const foo &f ) { return f.ch == ch; } );

另一种方法是将搜索作为类本身的接口。例如

class foo {
public:
    foo(int flag, char ch):flag(flag), ch(ch) {}
    int flag;
    char ch;
    class find_by_ch
    {
    public:        
        find_by_ch( char ch ) : ch( ch ) {}
        bool operator ()( const foo &f ) const { return f.ch == ch; }
    private:
        char ch;
    };        
};
//...
auto it = std::find_if( vec.begin(), vec.end(), foo::find_by_ch( 'b' ) );

foo定义一个隐式构造函数,仅使用char作为参数。

foo(char ch) : ch(ch), flag(int()) {
}

添加默认参数到现有的构造函数

foo(char ch, int flag = int()) : ch(ch), flag(flag) {
}

AND重载比较操作符

bool operator ==(const char & rhs) {
    return ch == rhs;
}

你可以直接使用std::find

vector<foo>::iterator it = std::find(vec.begin(), vec.end(), 'b');
if (it != vec.end()) {
    ...    // do something
}

工作代码将看起来像

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class foo {
public:
    foo(char ch, int flag = int()) : flag(flag), ch(ch) {}
    int flag;
    char ch;
    inline bool operator ==(const char & rhs) { return ch == rhs; }
};
int main(void) {
    vector<foo> vec;
    vec.push_back(('a', 1));
    vec.push_back(('b', 2));
    vec.push_back(('c', 3));
    vector<foo>::iterator it = find(vec.begin(), vec.end(), 'b');
    if (it != vec.end())
        cout << "found" << endl;
    return 0;
}

如果向量是排序的(如在您的示例中),您可以使用lower_bound来获得对数性能。如果向量没有排序,您可以使用find来实现线性性能。