使结构体可哈希化?

45

我正在尝试创建一个类似于[petInfo : UIImage]()这样的字典,但我遇到了错误Type 'petInfo' does not conform to protocol 'Hashable'。我的petInfo结构体如下:

struct petInfo {
    var petName: String
    var dbName: String
}

所以我希望以某种方式使其可哈希,但它的组件都不是整数,这就是var hashValue:Int所需的。 如果该结构体的字段都不是整数,我该如何使其符合协议呢?如果我知道dbName在该结构体的所有实例中都是唯一的,我能使用它来实现吗?

2个回答

65

只需在您的 hashValue 函数中返回 dbName.hashValue 即可。 FYI-哈希值不需要是唯一的。 要求是两个相等的对象必须具有相同的哈希值。

struct PetInfo: Hashable {
    var petName: String
    var dbName: String

    var hashValue: Int {
        return dbName.hashValue
    }

    static func == (lhs: PetInfo, rhs: PetInfo) -> Bool {
        return lhs.dbName == rhs.dbName && lhs.petName == rhs.petName
    }
}

1
哦,好的,谢谢你告诉我!你介意解释一下你添加的 static func 吗? - MarksCode
1
Hashable扩展自Equatable。请查阅两个协议的文档,了解==函数的详细解释。 - rmaddy

37

从Swift 5开始,var hashValue:Int已被废弃,推荐使用func hash(into hasher: inout Hasher)(在Swift 4.2中引入),因此要更新@rmaddy给出的答案,请使用:

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

5
由于String已经继承了Hashable,因此您只需要说hasher.combine(dbName)。同时,您需要实现==运算符,并且“用于哈希的组件必须与在类型的==运算符实现中进行比较的组件相同”,定义在这里 - jangelsb
@jangelsb 提到了 String 的好处 - 已更新。关于 Hashable 协议的一般性扩展,我不会在这个答案中详细阐述,因为它只是原始答案的附录。 - ChrisH
1
@jangelsb的评论非常有价值!实现==是使其正常工作绝对必要的。 - ixany

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接