Search code examples
swifthashableequatable

Swift: Hashable struct with dictionary property


I have a struct in Swift that looks like this:

internal struct MapKey {
    internal let id: String
    internal let values: [String:String]
}
extension MapKey: Equatable {}
func ==(lhs: MapKey, rhs: MapKey) -> Bool {
    return lhs.id == rhs.id && lhs.values == rhs.values
}

I now have the need to use MapKey as the key in a Swift dictionary, which requires MapKey to conform to the Hashable protocol.

What would a correct implementation of Hashable be for a struct like this one?

extension MapKey: Hashable {
    var hashValue: Int {
        return ??? // values does not have a hash function/property.
    }
}

I've been doing some research but failed to identify what the proper way to hash a dictionary is, as I need to be able to generate a hash value for values property itself. Any help is much appreciated.


Solution

  • I think you need to review your data model if you have to use a whole struct as a dictionary key. Anyhow, here's one way to do it:

    internal struct MapKey: Hashable {
        internal let id: String
        internal let values: [String:String]
    
        var hashValue: Int {
            get {
                var hashString = self.id + ";"
                for key in values.keys.sort() {
                    hashString += key + ";" + values[key]!
                }
    
                return hashString.hashValue
            }
        }
    }
    
    func ==(lhs: MapKey, rhs: MapKey) -> Bool {
        return lhs.id == rhs.id && lhs.values == rhs.values
    }
    

    This assumes that you don't have semicolon (;) in id or in the keys and values of values. Hasable implies Equatable so you don't need to declare it conforming to Equatable again.