Swift:具有字典属性

时间:2016-06-23 20:06:11

标签: swift hashable equatable

我在Swift中有一个结构,如下所示:

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
}

我现在需要使用MapKey作为Swift字典中的键,这需要MapKey符合Hashable协议。

对于像这样的结构,Hashable的正确实现是什么?

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

我一直在做一些研究,但未能确定散列字典的正确方法是什么,因为我需要能够为属性本身生成散列值。非常感谢任何帮助。

3 个答案:

答案 0 :(得分:4)

如果必须使用整个结构作为字典键,我认为您需要检查数据模型。无论如何,这是一种方法:

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
}

这假设您在;id的键和值中没有分号(values)。 Hasable隐含Equatable,因此您无需再次声明它符合Equatable

答案 1 :(得分:1)

由于id和值都是不可变的,因此可以将它们用作equals和hashValue的基础。 但是 - 如果MapKey.id(名称有点暗示)唯一标识MapKey(至少在一个字典的上下文中) 那么使用MakKey.id作为==运算符以及hashValue

的基础既简单又高效
    internal struct MapKey: Hashable {
        internal let id: String
        internal let values: [String:String]

        var hashValue: Int {
            get { return  self.id.hashValue}
        }
    }

    func ==(lhs: MapKey, rhs: MapKey) -> Bool {
        return lhs.id == rhs.id
    }

答案 2 :(得分:0)

基金会数据类型在Swift 4.2中是可哈希的,您只需要让您的MapKey结构符合哈希协议即可:

struct MapKey: Hashable {
    let id: String
    let values: [String: String]
}

如果要使用一个类,则需要使用conform hash(:) func,如下所示:

class MapKey: Hashable {
    static func == (lhs: MapKey, rhs: MapKey) -> Bool {
        return lhs.id == rhs.id && lhs.values == rhs.values
    }

    let id: String = ""
    let values: [String: String] = [:]

    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
        hasher.combine(values)
    }
}