假设我们有一个C ++ class { std::string name; std::string surname /*..other members..*/};
我们希望它可以通过2个字符串(name,surname)在向量内搜索。怎么办这样的事情?我应该实施哪些成员/操作员重载?还是一些散列函数?
答案 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)
;该
反向显然不能持有,但应该有一个高
它可能对任意两个a
和b
。
例如,在您的情况下,要按姓名和姓氏进行匹配 可能会定义:
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
。)
根据类的语义,它可能有意义 提供一组这些。