【问题标题】:Implementing a hash combiner in Swift在 Swift 中实现哈希组合器
【发布时间】:2017-03-06 13:34:33
【问题描述】:

我正在扩展 struct 以符合 Hashable。我将使用DJB2 哈希组合器来完成此操作。

为了方便为其他事情编写散列函数,我想扩展Hashable 协议,以便我的散列函数可以这样编写:

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

但是当我尝试编写实现 `combineHash(with:) 的 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 'Hashable' 只能用作通用约束,因为它具有 Self 或关联的类型要求

这是 Swift 不允许我做的事情,还是我只是做错了并且收到了无用的错误消息?


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

【问题讨论】:

  • @JAL 不错的——里面有有用的信息!特别是 Swift 的哈希值类型是带符号的 int,所以我的代码会像这里给出的那样表现不佳!
  • 是的,我遇到了类似的问题。 Martin 对 Boost hash combine 函数的 Swift 翻译是您工具箱中的一个很棒的函数。
  • @Benjohn:只有有符号整数的右移才能保留符号位。你的左移没有问题。
  • @MartinR 啊,好吧,我原来的哈希还不错吧? :-) 直到现在我才注意到您还编写了有关 Jal 链接到的哈希的代码审查!你们两个就像一个打击犯罪的二人组,防止碰撞并保持巨大的 O 期望 - 我感谢你们!

标签: swift hash


【解决方案1】:

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

https://developer.apple.com/documentation/swift/hashable

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)
    }

}

【讨论】:

    【解决方案2】:

    如果P,则不能定义P 类型的参数 是具有Self 或相关类型要求的协议。 在这种情况下,它是 Equatable 协议,Hashable 继承,它有一个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
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-25
      • 2012-05-27
      • 2017-03-20
      • 1970-01-01
      相关资源
      最近更新 更多