在Swift中实现散列组合器 [英] Implementing a hash combiner in Swift

查看:173
本文介绍了在Swift中实现散列组合器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我扩展了 struct 符合 Hashable 。我将使用 DJB2 散列组合器来完成此操作。

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

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

但是,当我尝试写入扩展到 Hashable 时,实现`combineHash(with :),如下所示:

 扩展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的评论链接至一个快速哈希函数的代码审查,这也是马丁提供的下面接受的答案!他在讨论中提到了一个不同的散列组合器,它基于c ++ boost库中的一个。讨论真的值得一读。替代组合器的碰撞更少(在测试过的数据上)。

解决方案

您无法定义 P 如果 P
是一个协议,它有 Self 或关联类型要求。
在这种情况下,它是 Equatable 协议,其中 Hashable
继承, Self 要求:

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

您可以做的是定义一个泛型方法:

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


I'm extending a struct conform to Hashable. I'll use the DJB2 hash combiner to accomplish this.

To make it easy to write hash function for other things, I'd like to extend the Hashable protocol so that my hash function can be written like this:

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

But when I try to write the extension to Hashable that implements `combineHash(with:), like this:

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

… then I get this compilation error:

/Users/benjohn/Code/Nice/nice/nice/CombineHash.swift:12:43: Protocol 'Hashable' can only be used as a generic constraint because it has Self or associated type requirements

Is this something that Swift won't let me do, or am I just doing it wrong and getting an unhelpful error message?


Aside A comment from JAL links to a code review of a swift hash function that is also written by Martin who provides the accepted answer below! He mentions a different hash combiner in that discussion, which is based on one in the c++ boost library. The discussion really is worth reading. The alternative combiner has fewer collisions (on the data tested).

解决方案

You cannot define a parameter of type P if P is a protocol which has Self or associated type requirements. In this case it is the Equatable protocol from which Hashable inherits, which has a Self requirement:

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

What you can do is to define a generic method instead:

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

这篇关于在Swift中实现散列组合器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆