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

How to make class searchable inside vector?

本文关键字:搜索 向量 何使类      更新时间:2023-10-16

>假设我们有一个C++class { std::string name; std::string surname /*..other members..*/};我们希望它可以通过那 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
}

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

在向量中,使用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.)

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