Swift Set of Structure Types Swift Set of Structure Types swift swift

Swift Set of Structure Types


Update: As of Swift 4.1 (Xcode 9.4) the compiler can synthesizethe == and hashValue methods if all members of the struct areEquatable/Hashable. Therefore is suffices to declare the conformance:

struct Cube: Hashable {    var x: Int    var y: Int    var z: Int    var width: Int}

Previous answer for older Swift versions:

First of all, Hashable extends Equatable, so you must implementa == operator which compares two values, using all propertieswhich uniquely identify a cube:

func ==(lhs: Cube, rhs: Cube) -> Bool {    return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.width == rhs.width}

The Hashable protocol only requires that

x == y implies x.hashValue == y.hashValue

so

var hashValue: Int {    return 0}

would be a valid (and working) implementation. However, this wouldput all objects in the same hash bucket of a set (or dictionary),which is not effective. A better implementation is for example

struct Cube: Hashable {    var x: Int    var y: Int    var z: Int    var width: Int        var hashValue: Int {        return x.hashValue ^ y.hashValue ^ z.hashValue ^ width.hashValue    }}

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 distinguishdifferent values better, so that the set operations become faster.On the other hand, the computation of the hash function itselfwould be slower. Therefore I would look for a "better" hash functiononly if the set operations turn out to be a performance bottleneck in your program.


Implementing Hashable protocol consists of two things. First is implementing hashValue 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 is hashValue. If hashValue returns same value for two structures, then equality between them will be determined by calling equality operator that would otherwise be skipped.

struct Cube: Hashable {    // satisfy Hashable requirement    var hashValue: Int {        get {            // you can return any integer here            return x &+ y &+ z &+...            // or even the same one for all structs            return 0        }    }}// satisfy Equatable requirementfunc ==(lhs: Cube, rhs: Cube) -> Bool {    return lhs.x == rhs.x && lhs.y == rhs.y .....}