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)]
就很好了。