如何在unordered_set
中存储班级的对象?我的程序需要经常检查此unordered_set
中是否存在对象,如果存在,则对该对象进行一些更新。
我已经在线查看了如何使用unordered_set
,但遗憾的是大多数教程都是关于在int
或string
类型上使用它。但是我如何在课堂上使用它呢?如何定义哈希函数以使以下示例中的node_id
成为unordered_set
的关键字?
#include <iostream>
#include <unordered_set>
using namespace std;
// How can I define a hash function that makes 'node' use 'node_id' as key?
struct node
{
string node_id;
double value;
node(string id, double val) : node_id(id), value(val) {}
};
int main()
{
unordered_set<node> set;
set.insert(node("1001", 100));
if(set.find("1001") != set.end()) cout << "1001 found" << endl;
}
答案 0 :(得分:5)
您可以尝试使用以下哈希函数对象(它非常基本,因此您可能需要对其进行改进以避免太多冲突)。
struct node_hash {
std::size_t operator()(const node& _node) const {
return std::hash<std::string>()(_node.node_id);
}
}
// ...
std::unordered_set<node, node_hash> node_set;
但是,正如其中一条评论指出的那样,最好在这里使用std::unordered_map<std::string, double>
。
答案 1 :(得分:1)
您需要实现自定义哈希函数(我建议使用Boost库中的函数)来执行此操作。 C ++允许您使用unordered_set保存指向类对象的指针。在大多数情况下,这应该可以解决问题。
答案 2 :(得分:1)
我同意ArchbishopOfBanterbury,对于您的特定用例,std::unordered_map<std::string, double>
可能是更好的选择。但是,如果由于某些原因要坚持使用unordered_set
,则也可以使用lambda expression而不是定义哈希函数。但是,您还必须提供比较功能(equal
)才能使代码正常工作。如果您希望两个node
实例具有相同的node_id
是相等的,则可以使用以下代码:
auto hash = [](const node& n){ return std::hash<std::string>()(n.node_id); };
auto equal = [](const node& n1, const node& n2){ return n1.node_id == n2.node_id; };
std::unordered_set<node, decltype(hash), decltype(equal)> set(8, hash, equal);
但是,如果要使用std::unordered_set::find()
,则不能简单地向该函数提供字符串(例如"1001"
),因为它希望将node
对象用作参数。不过,以下代码(创建一个临时对象)可以解决问题:
set.insert(node("1001", 100));
if (set.find(node("1001", 0)) != set.end())
std::cout << "1001 found" << std::endl;
请注意,尽管插入的1001 found
的{{1}}与指定给value
的{{1}}的{{1}}不同,但输出node
却被打印了。 value
函数(分别为100和0)。这是因为比较功能node
仅在检查相等性时考虑find()
。
答案 3 :(得分:0)
由于这是Google C++ unordered_set of objects
在Stack Overflow上获得的最高排名,因此我将发布一个简单但完全说明性且可复制/粘贴的可运行示例:
// UnorderedSetOfObjects.cpp
#include <iostream>
#include <vector>
#include <unordered_set>
struct Point
{
int x;
int y;
Point() { }
Point(int x, int y)
{
this->x = x;
this->y = y;
}
bool operator==(const Point& otherPoint) const
{
if (this->x == otherPoint.x && this->y == otherPoint.y) return true;
else return false;
}
struct HashFunction
{
size_t operator()(const Point& point) const
{
size_t xHash = std::hash<int>()(point.x);
size_t yHash = std::hash<int>()(point.y) << 1;
return xHash ^ yHash;
}
};
};
int main(void)
{
std::unordered_set<Point, Point::HashFunction> points;
points.insert(Point(1, 1));
points.insert(Point(2, 2));
points.insert(Point(1, 1)); // notice this is a duplicate with the 1st point so it won't change the set
std::cout << "points: " << "\n";
for (auto& point : points)
{
std::cout << "(" << point.x << ", " << point.y << ")" << "\n";
}
return 0;
}
答案 4 :(得分:0)
正如 How to specialize std::hash<Key>::operator() for user-defined type in unordered containers? 中所指出的,另一种选择是引入 == 运算符并将特化注入 std::hash