从哈希值计算中省略属性



有没有一种方法可以使用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个可能的哈希值,但有无限多的字符串。因此,必须有不同的字符串具有相同的哈希值。(

可散列集合(如SetDictionary(在其实现中使用散列值(例如,将不同的对象放入不同的"桶"中(,但它们从不单独使用散列值来确定相等性。

==的默认实现比较所有(存储的(属性是否相等。因此,在您的情况下,如果item1item2具有相同的val1val2,但具有不同的date,则它们是不同的对象,即使它们具有相同的哈希值。

如果您希望具有相同val1val2但不同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。

最新更新