6

我在 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.
    }
}

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

4

3 回答 3

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
}

这假定您在 的键和值中或中没有分号 ( ;) 。暗示所以你不需要再次声明它符合。idvaluesHasableEquatableEquatable

于 2016-06-23T20:15:04.720 回答
1

由于 id 和 values 都是不可变的,两者都可以用作 equals 和 hashValue 的基础。但是 - 如果 MapKey.id(顾名思义)唯一标识 MapKey(至少在一个字典的上下文中),那么仅使用 MakKey.id 作为 == 运算符的基础既更容易也更高效作为哈希值

    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
    }
于 2016-06-23T20:23:01.157 回答
0

基础数据类型在 Swift 4.2 中是 Hashable 的,你只需要让你的 MapKey 结构符合 Hashable 协议:

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

如果你想使用一个类,你需要像这样遵循 hash(:) 函数:

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)
    }
}
于 2019-02-16T04:05:28.590 回答