Setup:

我想使用以下struct中的Set:

struct NumberPair: Hashable {
    let n1: Int
    let n2: Int

    static func == (lhs: NumberPair, rhs: NumberPair) -> Bool {
        lhs.n1 == rhs.n1 && lhs.n2 == rhs.n2 ||
        lhs.n2 == rhs.n1 && lhs.n1 == rhs.n2
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(n1)
        hasher.combine(n2)
    }
}  

我预计在空的Set中插入两个相等的元素(根据上面定义的函数)会得到一个只有一个元素的Set:

    var pairs: Set<NumberPair> = []
//…
    pairs.insert(NumberPair(n1: 1, n2: 2))
    pairs.insert(NumberPair(n1: 2, n2: 1))  

Problem:

然而,在第二次插入时,我得到了一个运行时错误

Fatal error: Duplicate elements of type 'NumberPair' were found in a Set.
This usually means either that the type violates Hashable's requirements, or
that members of such a set were mutated after insertion.  

当我在static func ==中设置断点时,这个断点没有命中.

Question:

为什么我的自定义相等函数没有被调用,以及如何正确地执行它?

推荐答案

您的hash()方法违反了Hashable协议的最重要要求:

两个相等的实例必须以相同的顺序在散列(into:)中将相同的值提供给Hasher.

示例:

let p1 = NumberPair(n1: 1, n2: 2)
let p2 = NumberPair(n1: 2, n2: 1)

print(p1 == p2) // true
print(p1.hashValue) // -386759992433315259
print(p2.hashValue) // -5091661336101841357

在这里,p1p2是"相等的",但产生不同的哈希值.

散列方法的实现方式必须是在交换n1n2时产生相同的结果,例如

func hash(into hasher: inout Hasher) {
    hasher.combine(min(n1, n2))
    hasher.combine(max(n1, n2))
}

func hash(into hasher: inout Hasher) {
    hasher.combine(n1 ^ n2)
}

Remark: The second one is simpler and perhaps faster, but m或e likely to cause hash collisions. struct Hasher and its combine(_:) method where introduced in Swift 4.2 (among other reasons) in 或der to get rid of “XOR hashing,” see SE-0206 SEHashable Enhancements.

Swift相关问答推荐

同步问题,发送Api Call之前未设置idToken

SwiftData查询按日期排序的项的属性数组

带有文本输入自动大小写修饰符的SwiftUI Textfield问题

SwiftUI map 旋转

它是RxSwift中直接用于可扩展视图的有效的可扩展BehaviorRelay值?

如何在每天午夜重置布尔值

在NavigationStack上设置拐角半径:SwiftUI中的无响应内容视图区

在SwiftUI中如何预览嵌套的ScrollView,以避免触发可刷新修饰符

避免 `(())` 显式指定 Void 类型的枚举关联值

将弱引用作为类函数引用传递时,弱引用无法按预期工作

覆盖一个子元素的 HStack 对齐方式

从文字创建数组时的 Swift 宏

如何在 SceneKit 上制作毛玻璃效果

swift 是否遇到 Java 的 2gb 最大序列化大小问题?

如何为 Swift UI 视图定义 struct ?

不支持用作符合协议 AnyObject 的具体类型

FCM 后台通知在 iOS 中不起作用

关闭 UITableViewRowAction

无法停止 AVPlayer

使用相机进行人脸检测