有没有一种方法可以使用hash(into:)
来计算结构/类的哈希值,同时省略使用某些属性?
即
struct CacheItem: Codable, Hashable {
let val1: Int
let val2: Int
let date: Date = Date()
func hash(into hasher: inout Hasher) {
hasher.combine(val1) // leave out date for computing hash value
hasher.combine(val2)
}
}
我希望这能奏效:
let cache = Set<CacheItem>()
let item1 = CacheItem(val1: 0, val2: 0)
let item2 = CacheItem(val1: 0, val2: 0)
cache.insert(item1)
assert(cache.contains(item2))
然而,它没有起作用。
Set
是唯一对象的集合,相等性基于与==
的比较。相等的对象必须具有相同的哈希值,但不能相反:不同的对象可以具有相同的散列值。(一个简单的例子:有2个64个可能的哈希值,但有无限多的字符串。因此,必须有不同的字符串具有相同的哈希值。(
可散列集合(如Set
和Dictionary
(在其实现中使用散列值(例如,将不同的对象放入不同的"桶"中(,但它们从不单独使用散列值来确定相等性。
==
的默认实现比较所有(存储的(属性是否相等。因此,在您的情况下,如果item1
和item2
具有相同的val1
和val2
,但具有不同的date
,则它们是不同的对象,即使它们具有相同的哈希值。
如果您希望具有相同val1
和val2
但不同date
的对象被视为相等,那么您必须自己实现==
:
struct CacheItem: Codable, Hashable {
// ...
static func ==(lhs: CacheItem, rhs: CacheItem) -> Bool {
return lhs.val1 == rhs.val1 && lhs.val2 == rhs.val2
}
}
然后
var cache = Set<CacheItem>()
let item1 = CacheItem(val1: 0, val2: 0)
let item2 = CacheItem(val1: 0, val2: 0)
cache.insert(item1)
print(cache.contains(item2))
将始终打印CCD_ 16。