在Swift中实现哈希合并器

时间:2017-03-06 13:34:34

标签: swift hash

我将struct延伸到Hashable。我将使用DJB2哈希合并器来完成此任务。

为了便于为其他事情编写哈希函数,我想扩展Hashable协议,以便我的哈希函数可以像这样编写:

extension MyStruct: Hashable {
  public var hashValue: Int {
    return property1.combineHash(with: property2).combineHash(with: property3)
  }
}

但是当我尝试将扩展名编写为实现`combineHash(和:)的Hashable时,就像这样:

extension Hashable {
  func combineHash(with hashableOther:Hashable) -> Int {
    let ownHash = self.hashValue
    let otherHash = hashableOther.hashValue
    return (ownHash << 5) &+ ownHash &+ otherHash
  }
}

...然后我收到了这个编译错误:

  

/Users/benjohn/Code/Nice/nice/nice/CombineHash.swift:12:43:Protocol&#39; Hashable&#39;只能用作通用约束,因为它具有Self或关联类型要求

这是Swift赢得不让我这么做的事情,还是我只是做错了并得到一条无用的错误信息?

除了来自JAL的评论链接到a code review of a swift hash function,该评论也是由马丁撰写的,他提供了下面接受的答案!他在讨论中提到了一个不同的哈希合并器,它基于c ++ boost库中的一个。讨论确实值得一读。替代组合器具有较少的冲突(在测试的数据上)。

2 个答案:

答案 0 :(得分:6)

如果P,您无法定义P类型的参数 是具有Self或相关类型要求的协议。 在这种情况下,它是Equatable协议Hashable inherits,具有Self要求:

public static func ==(lhs: Self, rhs: Self) -> Bool

您可以做的是定义一个通用方法:

extension Hashable {
    func combineHash<T: Hashable>(with hashableOther: T) -> Int {
        let ownHash = self.hashValue
        let otherHash = hashableOther.hashValue
        return (ownHash << 5) &+ ownHash &+ otherHash
    }
}

答案 1 :(得分:1)

使用Apple开发者文档中的hash(into :)方法

struct GridPoint {
var x: Int
var y: Int
}

extension GridPoint: Hashable {
static func == (lhs: GridPoint, rhs: GridPoint) -> Bool {
    return lhs.x == rhs.x && lhs.y == rhs.y
}

func hash(into hasher: inout Hasher) {
    hasher.combine(x)
    hasher.combine(y)
}
}

以下是文档的链接:https://developer.apple.com/documentation/swift/hashable