Swift 中的可散列枚举
Posted
技术标签:
【中文标题】Swift 中的可散列枚举【英文标题】:Hashable enum in Swift 【发布时间】:2016-05-16 13:16:48 【问题描述】:我想要一个枚举,其中包含两个具有 Hashable 关联类型的案例,每个案例都符合 Hashable,如下所示:
enum WordOrNumber
case Word(String)
case Number(Int)
我对散列的第一个想法如下:
extension WordOrNumber: Hashable
var hashValue: Int
switch self
case let .Word(word):
return word.hashValue & ~1 // ends in 0
case let .Number(number):
return number.hashValue | 1 // ends in 1
我不确定的是,这将如何与 Swift 的 Dictionary 和 Set 实现中的存储桶进行交互。
是用 LSB 还是 MSB 区分这两种情况更好,还是中间的某个地方更好?
我认为将 hashValues 左移 1 然后加 1 没有任何区别,但我很想知道情况是否如此。
编辑: 我刚刚对此进行了测试,看起来 Int 的 hashValue 就是值本身。这显然是一个问题,因为您经常会连续获得整数,例如在枚举 Bla: Int 中。所以我新的和改进的(?)hashValue 是:
extension WordOrNumber: Hashable
var hashValue: Int
switch self
case let .Word(word): // ends in 0
return word.hashValue << 1
case let .Number(number): // ends in 1
return number.hashValue << 1 &+ 1
上面关于LSB和MSB的问题仍然存在。
【问题讨论】:
实际上没有必要区分这两种情况。你想达到什么目的? 我不确定你的意思?肯定是String的hashValues和.Number(x) == .Word(y)的Int的hashValues有冲突,有问题吗? 为什么会有问题?哈希函数并不意味着返回唯一的结果,真正重要的是相等的定义(Equatable
,函数==
)。我还假设Set
和Dictionary
都使用辅助散列函数。
来自 Swift 文档:“集合和字典的性能取决于散列值,该散列值分别最小化其关联元素和键类型的冲突。”所以这是一个相关数据散列之间的冲突可能有多频繁的问题。
【参考方案1】:
有类似的东西:
extension WordOrNumber: Hashable
var hashValue: Int
switch self
case .Word(let value):
return value.hashValue
case .Number(let value):
return value.hashValue
static func ==(lhs: WordOrNumber, rhs: WordOrNumber) -> Bool
switch (lhs, rhs)
case (.Word(let lhsValue), .Word(let rhsValue)):
return lhsValue == rhsValue
case (.Number(let lhsValue), .Number(let rhsValue)):
return lhsValue == rhsValue
default:
return false
...应该够了。
【讨论】:
以上是关于Swift 中的可散列枚举的主要内容,如果未能解决你的问题,请参考以下文章