[英]How can I overload equal method to make different objects have same hashcode value in unordered_multimap in my case
I have written a map like this:我写了一个这样的地图:
unordered_multimap<Point, int, StrHash, StrCompare> map
StrHash()
is to create hashcode and StrCompare()
is to solve the hashcode collision. StrHash()
是创建哈希码, StrCompare()
是解决哈希码冲突。 but I want to do something as follow:但我想做以下事情:
A and B have different hashcode value,but A equal to B, then run the StrCompare()
method. A 和 B 具有不同的哈希码值,但 A 等于 B,然后运行
StrCompare()
方法。 how can I do that,just like Point A(220,119)
and Point B(220,220)
have different hashcode.我该怎么做,就像
A(220,119)
点A(220,119)
和Point B(220,220)
有不同的哈希码一样。 Can I overload hashcode equal method to make A == B
?我可以重载 hashcode equal 方法使
A == B
吗? In my case, I want to get the Points
,which compare with each others (abs(ax - bx) + abs(ay - by) < 3)
.在我的情况下,我想得到
Points
,它们相互比较(abs(ax - bx) + abs(ay - by) < 3)
。 just like, Point(220,220)(220,119)(220,118)(220,220)
my code is as follow:就像
Point(220,220)(220,119)(220,118)(220,220)
我的代码如下:
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <math.h>
#include <string>
using std::string;
#include <unordered_map>
using std::unordered_multimap;
using namespace std;
using namespace cv;
class StrHash{
public:
size_t operator()(const Point a) const {
return a.x * 1000 + a.y;
}
};
class StrCompare{
public:
bool operator()(const Point& a, const Point& b) const {
if (abs(a.x - b.x) + abs(a.y - b.y) < 3) {
return true;
}
else
return false;
}
};
int main()
{
unordered_multimap<Point, int, StrHash, StrCompare> map;
map.insert(make_pair(Point(30, 120), 1));
map.insert(make_pair(Point(220, 120), 2));
map.insert(make_pair(Point(220, 120), 3));
map.insert(make_pair(Point(220, 120), 4));
map.insert(make_pair(Point(220, 119), 5));
map.insert(make_pair(Point(30, 120), 6));
unordered_multimap<Point, int, StrCompare>::iterator iter1;
unordered_multimap<Point, int, StrCompare>::iterator iter2;
for (iter1 = map.begin(); iter1 != map.end();)//
{
int num = map.count((*iter1).first);
iter2 = map.find((*iter1).first);
if (num > 2) {
for (int i = 1; i <= num; i++)
{
cout << (*iter2).first << " " << i << endl;
iter2++;
}
iter1++;
}
else {
iter1++;
}
}
}
This isn't how hash maps/ unordered_map
work.这不是哈希映射/
unordered_map
工作方式。 By definition if the hashes are unequal the objects are unequal.根据定义,如果散列不相等,则对象不相等。 Not only that, but your "equality" operator allows things like
A(220,119)
, B(220,220)
, C(220, 222)
where A == B and B == C but A != C. I can't see any way to accomplish what you ask in this question, but is there perhaps a real problem you're trying to solve?不仅如此,您的“相等”运算符还允许
A(220,119)
、 B(220,220)
、 C(220, 222)
,其中 A == B 和 B == C 但 A != C。我看不到有什么方法可以完成您在这个问题中提出的问题,但是您是否正在尝试解决真正的问题?
Based on your comments, it sounds like you want std::vector
instead of std::unordered_map
.根据您的评论,听起来您想要
std::vector
而不是std::unordered_map
。 Then you just use std::find
to find the element you care about instead of going through the indirection of having a no-op hash.然后您只需使用
std::find
来查找您关心的元素,而不是通过具有无操作哈希的间接方法。
Got to say this as it's so much easier if your error tolerance will allow it: you could just round your values to the nearest multiple of 2 or 3.不得不说这是因为如果您的容错允许它会容易得多:您可以将您的值四舍五入到最接近的 2 或 3 的倍数。
MarkB's suggestion of using a vector
is excellent... just listing some others for the intellectual interest. MarkB 的使用
vector
的建议非常好......只是为了知识分子的兴趣列出了一些其他的。
It is possible to get the functionality you want using an unordered_map
, but not very cleanly: you'll need the map-using code to orchestrate the logic for approximate equality.使用
unordered_map
可以获得您想要的功能,但不是很干净:您需要使用地图的代码来编排近似相等的逻辑。 First, the equality function must check for actual equality:首先,相等函数必须检查实际相等:
struct PointCompare{
bool operator()(const Point& a, const Point& b) const {
return a.x == b.x && a.y == b.y;
}
};
Then, you'll need a support function like this:然后,您将需要这样的支持功能:
template <class Map>
auto approx_find(Map& map, const Point& point) -> decltype(map.begin())
{
decltype(map.end()) it;
for (int x_offset = -2; x_offset <= 2, ++x_offset)
for (int y_offset = -2; y_offset <= 2, ++y_offset)
if (abs(x_offset) + abs(y_offset) < 3 &&
(it = map.find({point.x + x_offset, point.y + y_offset})) != map.end())
return it;
return map.end();
}
Then, you can use the returned iterator to see if Point
you're thinking of inserting will be a duplicate, as well as for lookup, erase
ing etc..然后,您可以使用返回的迭代器来查看您正在考虑插入的
Point
是否会重复,以及用于查找、 erase
等。
Note that the performance will not be great.请注意,性能不会很好。 Each
approx_find
is effectively searching around the Point
argument as follows:每个
approx_find
都有效地搜索Point
参数,如下所示:
<------------- X axis -------------->
^
| 0,-2
| -1,-1 0,-1 1,-1
Y axis -2,0 -1,0 0,0 1,0, 2,0
| -1,1 0,1 1,1
| 0,2
v
All up, that's 13 lookups - scattered more-or-less randomly around the hash table's buckets so not particularly cache friendly - instead of the usual 1.总而言之,这是 13 次查找 - 或多或少随机地分散在哈希表的存储桶周围,因此不是特别适合缓存 - 而不是通常的 1 次。
A completely different option is to use an unordered_multimap
to keep track of the Point
s in a general area of the graph - close enough that they might satisfy the <3
proximity test.一个完全不同的选择是使用
unordered_multimap
来跟踪图的一般区域中的Point
s - 足够接近它们可能满足<3
邻近测试。 For example:例如:
std::unordered_multimap<Point, Point> areas;
Point p = { ...whatever... };
// keys for nearby points:
Point around[] = { { (p.x - 2) / 3 * 3, (p.y - 2) / 3 * 3 },
{ (p.x + 2) / 3 * 3, (p.y - 2) / 3 * 3 },
{ (p.x - 2) / 3 * 3, (p.y + 2) / 3 * 3 },
{ (p.x + 2) / 3 * 3, (p.y + 2) / 3 * 3 } };
For each of the four around[]
entries, do a find
in the multimap
to see if there's an exact or approximate match: that reduces the 13 table probes to just 4. Each multimap
key won't ever map to more than 2 entries, as the only non-approximate-clash would be for two Points
at opposite corners of an area.对于四个
around[]
条目中的每一个,在多multimap
进行find
以查看是否存在精确或近似匹配:这将 13 个表探针减少到只有 4 个。每个多multimap
键永远不会映射到超过 2 个条目,因为唯一的非近似冲突是区域对角的两个Points
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.