如何使类可以在向量内搜索?

时间:2014-01-21 12:48:15

标签: c++ class search vector

假设我们有一个C ++ class { std::string name; std::string surname /*..other members..*/};我们希望它可以通过2个字符串(name,surname)在向量内搜索。怎么办这样的事情?我应该实施哪些成员/操作员重载?还是一些散列函数?

2 个答案:

答案 0 :(得分:2)

如果您使用std::vector,最好的方法可能是使用std::find_if()。这将允许您定义将应用于每个元素的自定义谓词,搜索您需要的任何内容。谓词可以是任何可调用类型;如果您使用的是C ++ 11,则lambda是理想的。

以下是使用内联lambda的示例(我假设Name类与您在问题中描述的一样):

std::vector<Name> vec;
// populate the vector with names...

auto iter = std::find_if(
    vec.begin(),
    vec.end(),
    [](const Name &n) { return n.name == "Random" && n.surname == "Person"; }
);

if (iter != vec.end()) {
    // search was successful
}

您还可以使用存储的lambdas或预定义的函数/仿函数作为谓词。

答案 1 :(得分:1)

在向量内,使用std::find,您需要operator== (逻辑上应该伴随operator!=;它是 非常糟糕的做法只提供一个,即使标准 图书馆不要求它)。或者您可以使用std::find_if, 并明确提供比较。

如果要对矢量进行排序,请使用std::lower_bounds 它,或将对象放在std::set中(或将它们用作关键词 std::map),您需要operator<(这应该意味着。{ 运营商<=>>=也是一致的)。再次, 您可以提供明确的比较。 !(a < b) && !(b < a)在这里意味着平等,所以如果你实现所有 六个运营商,你可能也意味着a == b

对于std::unordered_set(或unordered_map中的关键字,您可以 还需要一个哈希函数,它必须与之一致 operator==;即如果a == b,则hash(a) == hash(b);该 反向显然不能持有,但应该有一个高 它可能对任意两个ab

例如,在您的情况下,要按姓名和姓氏进行匹配 可能会定义:

class MatchName
{
    std::string targetName;
    std::string targetSurname;
public:
    MatchName( std::string const& targetName, std::string const& targetSurname )
        : targetName( targetName )
        , targetSurname( targetSurname )
    {
    }
    bool operator()( ClassType const& obj ) const
    {
        return obj.name == targetName
            && obj.surname == targetSurname;
    }
}

或者如果您想保持数据排序:

class OrderByName
{
public:
    bool operator()( ClassType const& lhs, ClassType const& rhs ) const
    {
        return lhs.name < rhs.name
            || (lhs.name == rhs.name && lhs.surname < rhs.surname);
    }
};

和无序容器:

template <typename T> struct Hash;
template<>
struct Hash<ClassType>
{
    bool operator()( ClassType const& obj ) const
    {
        return 127 * hash<std::string>( obj.name )
            + hash<std::string( obj.surname );
    }
};

(如果您使用的是operator==,则可能需要定义 std::hash的特定实例,以便编译器 默认会选择它;这是你难得的一次 可以,实际上几乎必须添加一些东西到命名空间 std。)

根据类的语义,它可能有意义 提供一组这些。