Rei*_*ner 2 set hashable swift
设置:
\n我想使用Set以下之一struct:
struct NumberPair: Hashable {\n let n1: Int\n let n2: Int\n\n static func == (lhs: NumberPair, rhs: NumberPair) -> Bool {\n lhs.n1 == rhs.n1 && lhs.n2 == rhs.n2 ||\n lhs.n2 == rhs.n1 && lhs.n1 == rhs.n2\n }\n \n func hash(into hasher: inout Hasher) {\n hasher.combine(n1)\n hasher.combine(n2)\n }\n} \nRun Code Online (Sandbox Code Playgroud)\n我预计将两个相等的元素(根据上面定义的函数)插入到空Set结果中会Set产生一个元素:
var pairs: Set<NumberPair> = []\n//\xe2\x80\xa6\n pairs.insert(NumberPair(n1: 1, n2: 2))\n pairs.insert(NumberPair(n1: 2, n2: 1)) \nRun Code Online (Sandbox Code Playgroud)\n问题:
\n但是,在第二次插入时我收到运行时错误
\nFatal error: Duplicate elements of type 'NumberPair' were found in a Set.\nThis usually means either that the type violates Hashable's requirements, or\nthat members of such a set were mutated after insertion. \nRun Code Online (Sandbox Code Playgroud)\n当我在 中设置断点时static func ==,不会命中断点。
问题:
\n为什么我的自定义相等函数没有被调用,以及如何正确执行?
\n您的hash()方法违反了协议最重要的要求Hashable:
\n\n两个相等的实例必须以相同的顺序向 hash(into:) 中的 Hasher 提供相同的值。
\n
例子:
\nlet p1 = NumberPair(n1: 1, n2: 2)\nlet p2 = NumberPair(n1: 2, n2: 1)\n\nprint(p1 == p2) // true\nprint(p1.hashValue) // -386759992433315259\nprint(p2.hashValue) // -5091661336101841357\nRun Code Online (Sandbox Code Playgroud)\n这里p1和p2是 \xe2\x80\x9cequal\xe2\x80\x9d 但产生不同的哈希值。
哈希方法的实现方式必须能够在交换n1和n2时产生相同的结果,例如
func hash(into hasher: inout Hasher) {\n hasher.combine(min(n1, n2))\n hasher.combine(max(n1, n2))\n}\nRun Code Online (Sandbox Code Playgroud)\n或者
\nfunc hash(into hasher: inout Hasher) {\n hasher.combine(n1 ^ n2)\n}\nRun Code Online (Sandbox Code Playgroud)\n备注:第二个更简单,也许更快,但更可能导致哈希冲突。struct Hasher及其combine(_:)在 Swift 4.2 中引入的方法(以及其他原因),以摆脱 \xe2\x80\x9cXOR 哈希,\xe2\x80\x9d 请参阅SE-0206 SEHashable 增强。
| 归档时间: |
|
| 查看次数: |
63 次 |
| 最近记录: |