swift - 从哈希值计算中省略一个属性
问题描述
有没有一种方法可以hash(into:)
用来计算结构/类的哈希值,同时省略某些属性的使用?
IE
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))
但是,它没有用。
解决方案
ASet
是唯一对象的集合,相等性基于与 的比较==
。相等的对象必须具有相同的哈希值,但不能相反:不同的对象可以具有相同的哈希值。(一个简单的例子:有 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))
将始终打印true
.
推荐阅读
- python - 使用 Shell 脚本在列表中提取不带扩展名的文件名
- r - 根据 R 中不同字段中的值添加新字段的有效方法
- javascript - JS | getContext('2d') 的问题
- c# - 如何在这里实现开关而不是 if 和 else if ?
- angular - 将角度服务文件拆分为两个文件
- python-3.x - 为每个列表值添加一个项目
- python - Python:在for循环中强制字典中的值复制
- python - 使用 Python 删除和替换特定的字符串索引
- regex - 无法正确解析文件;全球不工作
- c++ - 如何实现与参数顺序无关的 std::same_as 的广义形式(即对于两个以上的类型参数)?