I wonder if there is a general all-around solution for a hash map
for coordinates (in 2d or 3d, i.e. a vector of doubles)?
An example here demonstrates how to create a custom hash-map for pair<int,int>
,
but it does not seem to be trivial to come-up with an unique map from pair<double,double>
(which could represent a 2d coordinate) to size_t
.
I know that i can use ordered maps by providing comparator object, but for my application there is no need to order them and hash-maps seems to be faster anyway.
However since i'm a newcomer to all this hash
stuff, i am kind of lost on how to proceed.
p/s/ i use c++11.
In the 3D case,
std::unordered_map<std::tuple<double, double, double>, your_value_type>
should work fine for you, assuming you are doing exact lookups.std::tuple<...>
defines equality and hash functions for you, based on the equality and hash functions of the types it is aggregating.The 2D case is of course the same, but using a
std::tuple<double, double>
.Edit: Sorry for misinformation. There actually is not a default hash defined for
std::tuple
. To use this approach, you would have to define ahash_tuple
templated functor class and then use that in thestd::unordered_map
. Other answers show how to do that part.What about using
hash_combine
from Boost?http://www.boost.org/doc/libs/1_53_0/doc/html/hash/combine.html
I cannot comment on Andre's answer because I do not have enough reputation yet, but anyone trying to create a hash function using ^ (XOR) should note that XOR is associative. In other words
a ^ (b ^ c) == (a ^ b) ^ c
. This means thatwhich is the return value of Andre's answer, is the same as:
which itself is, due to the commutative nature of XOR (
a ^ b == b ^ a
), equivalent to:What all of this means is that the hash method I am referring to will, for distinct
a
,b
, andc
, return the same hash for(a,b,c)
as it will for(c,b,a)
. In other words the x and z coordinates are order independent / insensitive.Depending on how you are using this hash method this might not be a problem. However, if for example the points you were hashing were aligned to a grid you would receive an inordinate number of hash collisions.
I would replace the expression in the return statement in Andre's answer with the one below. This should be order dependent / sensitive.
To avoid extra dependencies, you can use
std::hash
. Here's an example using the code from the link you posted, and updated to use astd::pair<double,double>
:As I said before, if you wish to use another structure you have to adapt both the
pairHash
class andpairEquals
structoperator()
to appropriately hash and compare the new keys, respectively.Cheers
EDIT :