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,函数==)。我还假设SetDictionary 都使用辅助散列函数。 来自 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 中的可散列枚举的主要内容,如果未能解决你的问题,请参考以下文章

具有可互换属性的可散列结构?

Swift 5.+ - 使类可散列?

列表不可散列,但元组可散列?

自动使类可散列

Numpy 数组是可散列的吗?

字典和集合