Say I have a struct
, which could be anything:
struct Cube {
var x: Int
var y: Int
var z: Int
var width: Int
// ...
}
How do I then create a Set
of these points, such that there will be no two objects with the same properties?
let points: Set<Cube> = Set()
// Type ‘Cube’ does not conform to protocol ‘Hashable’
But it’s not immediately obvious how to implement hashable. From what I read, I need to make a hash function, but that doesn’t look easily possible with the amount of properties I have in the struct.
Implementing
Hashable
protocol consists of two things. First is implementinghashValue
and second one is implementing equality operator.To have working
Hashable
protocol important part is equality operator. It has to be implemented in a way that returns true only and only then if two structures contain same values.On the other hand your
hashValue
implementation can return literally anything as long as same structure will always return same value.The only thing that
hashValue
influences is how fast will your code work, because when you add or look up for values, first code that will run ishashValue
. IfhashValue
returns same value for two structures, then equality between them will be determined by calling equality operator that would otherwise be skipped.First of all,
Hashable
extendsEquatable
, so you must implement a==
operator which compares two values, using all properties which uniquely identify a cube:The
Hashable
protocol only requires thatso
would be a valid (and working) implementation. However, this would put all objects in the same hash bucket of a set (or dictionary), which is not effective. A better implementation is for example
Here the "XOR" operator
^
is chosen because it cannot overflow. You could also use the "overflow operator"&+
.More sophisticated hash functions would be able to distinguish different values better, so that the set operations become faster. On the other hand, the computation of the hash function itself would be slower. Therefore I would look for a "better" hash function only if the set operations turn out to be a performance bottleneck in your program.
Update: As of Swift 4.1 (Xcode 9.4) the compiler can synthesize the
==
andhashValue
methods if all members of the struct areEquatable/Hashable
. Therefore is suffices to declare the conformance: