Swift 5.0 “设置”允许重复值

Swift 5.0 "Set" allowing duplicate values

提问人:Kendall Helmstetter Gelner 提问时间:7/9/2019 更新时间:7/9/2019 访问量:1092

问:

在 Swift 5.0 Playground 中,我正在尝试扩展,以便它将点视为哈希和相等的整数值。CGPoint

令我惊讶的是,即使在覆盖和开启之后,一组 CGPoints 仍然具有相似的值作为独立点,即使两个元素应该碰撞并且只保留一个。您是否需要重写其他方法才能按预期完成此工作?hash()==CGPointCGPoint

P.S. 在实践中最好不要这样做,因为它可能会影响系统,最好提供某种包装器来管理平等。但我想知道为什么这不起作用。

Playground 内容以及执行后给出的结果:

// Extension to treat points as integer values (not reccomended approach)
extension CGPoint : Hashable {
    public func hash(into hasher: inout Hasher) {
                hasher.combine(Int(x))
        hasher.combine(Int(y))
    }

    static public func == (lhs: CGPoint, rhs: CGPoint) -> Bool {
        return Int(lhs.x) == Int(rhs.x) && Int(lhs.y) == Int(rhs.y)
    }
}

var pSet : Set<CGPoint> = []

let p1 = CGPoint.zero
let p2 =  CGPoint(x: 20.1, y: 30)
let p3 =  CGPoint(x:20, y: 30)

pSet.insert(p1) // inserted true
pSet.insert(p2) // inserted true
pSet.insert(p3) // inserted true(!), should be false

p2 == p3 // true

pSet.count // 3(!), should be two
p2.hashValue  // Same as p3
p3.hashValue  // Same as p2

pSet // shows all three values, all points defined, should be two values only
Swift 哈希 相等

评论

1赞 rmaddy 7/9/2019
1. 您是否验证过您的电话正在被调用?2. 已经符合,因此您尝试实现自己的功能可能与现有实现相冲突。在扩展中执行此类操作是未定义的。hash(into:)CGPointEquatable==
0赞 3li 7/9/2019
我不确定,但从 Set 的 insert 方法的文档中我注意到了这一点:“如果集合中未包含 newMember,则返回 (true, newMember)。如果集合中已包含等于 newMember 的元素,则该方法返回 (false, oldMember),其中 oldMember 是等于 newMember 的元素。.我认为最后一位 sentese 有你问题的答案。In some cases, oldMember may be distinguishable from newMember by identity comparison or some other means."
2赞 Martin R 7/9/2019
将点插入到集合中时,不会调用方法。==
1赞 Martin R 7/9/2019
相关新闻: stackoverflow.com/q/38213286/1187415.

答:

3赞 rob mayoff 7/9/2019 #1

rmaddy 和 Martin R 发现了问题,但这里是一个答案:不使用您的函数。它使用标准库中定义的函数,因为在标准库中定义。你可以通过调用 is your function 来证明这一点。当您在 中插入一个点时,您会看到您的点没有运行。Set====Setprint==Setprint

评论

1赞 Kendall Helmstetter Gelner 7/9/2019
谢谢,我被我比较 p2 == p3 的行误导了,这产生了对该方法的一些调用,使我认为集合正在使用它。