Set方法states的文档:
返回值
insert如果集合中不包含(true, newMember)。如果集合中已包含一个等于newMember的元素,则该方法返回newMember,其中(false, oldMember)是等于oldMember的元素。
在某些情况下,newMember可以通过同一性比较或一些其他方式与oldMember区分。
newMember可以与他们所说的oldMember区分时,有哪些情况?有什么例子吗?
问题的原因:我有一个newMember包含不一定Set的对象。我的想法是使用Hashable为包装结构中的任何对象(基本上是从它的地址)获取散列值,但是文档中的上述位让我很谨慎。

最佳答案

如果有某种方法可以区分两个实例,即使它们通过Equatable==运算符实现比较相等,那么可以使用此方法将要插入的元素与memberAfterInsert返回的insert(_:)进行比较。
如文档所述,这方面的一个主要例子是身份比较(===)。比较相等的两个对象实例不一定是完全相同的实例(即具有相同的地址)。
例如:

class Foo : Hashable {

    static func ==(lhs: Foo, rhs: Foo) -> Bool {
        return lhs.foo == rhs.foo
    }

    var hashValue: Int {
        return foo
    }

    let foo: Int

    init(_ foo: Int) {
        self.foo = foo
    }
}

var set : Set = [Foo(10)]

let toInsert = Foo(10)
let result = set.insert(toInsert) // the element toInsert will compare equal to the element
                                  // already in the set, thus the element already in the
                                  // already in the set will be returned.

print(result) // (false, Foo) – false, as element was already in set
print(result.memberAfterInsert == toInsert) // true – obviously they were equal.
print(result.memberAfterInsert === toInsert) // false – but they weren't the same instance.

在使用基于标识的散列值的情况下,只要Equatable实现也依赖于标识,您不会违反Hashable的约定(与==相等的实例必须具有相同的hashValue)–尽管显然您无法使用标识来区分memberAfterInsert与您试图插入的元素。
但是值得注意的是,如果Set的等式实现完全基于标识,那么对于看起来应该是等价的对象,使用Element可能会导致令人惊讶的结果。例如,如果对象是不同的实例,那么拥有一组[Foo(5), Foo(5), Foo(5), Foo(5)]就很好了。

10-08 16:23