集合类型的哈希值
要将某个类型的元素存储在集合中,该类型必须是可哈希的,也就是说,该类型必须提供一种为自身计算哈希值的方法。哈希值是一个 Int
类型的值,对于所有相等的对象,其哈希值相同,即如果 a == b
,那么 a
的哈希值等于 b
的哈希值。
Swift 的所有基本类型(如 String
、Int
、Double
和 Bool
)默认都是可哈希的,因此可以用作集合的值类型或字典的键类型。没有关联值的枚举成员(如“枚举”部分所述)默认也是可哈希的。
注意
你可以让自定义类型遵循 Swift 标准库中的 Hashable
协议,从而将其用作集合的值类型或字典的键类型。有关实现所需的 hash(into:)
方法的信息,请参阅“Hashable”。有关遵循协议的信息,请参阅“协议”。
集合类型语法
Swift 集合的类型写作 Set<Element>
,其中 Element
是该集合允许存储的元素类型。与数组不同,集合没有等效的简写形式。
创建并初始化空集合
你可以使用初始化器语法来创建特定类型的空集合:
var letters = Set<Character>()
print("letters is of type Set<Character> with \(letters.count) items.")
// Prints "letters is of type Set<Character> with 0 items."
或者,如果上下文已经提供了类型信息,比如在函数参数中,或者有已经指定类型的变量或常量,你可以使用空数组字面量来创建一个空集合:
letters.insert("a")
// letters now contains 1 value of type Character
letters = []
// letters is now an empty set, but is still of type Set<Character>
使用数组字面量创建集合
你还可以使用数组字面量来初始化一个集合,这是一种将一个或多个值写成集合形式的便捷方式。
下面的示例创建了一个名为 favoriteGenres
的集合,用于存储 String
类型的值:
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
// favoriteGenres has been initialized with three initial items
favoriteGenres
变量被声明为“一个存储 String
类型值的集合”,写作 Set<String>
。由于这个特定的集合指定了值的类型为 String
,所以它只允许存储 String
类型的值。在这里,favoriteGenres
集合通过一个数组字面量进行初始化,该数组字面量包含三个 String
类型的值("Rock"
、"Classical"
和 "Hip hop"
)。
注意
favoriteGenres
集合被声明为变量(使用 var
关键字)而非常量(使用 let
关键字),因为在下面的示例中会对其中的元素进行添加和移除操作。
仅通过数组字面量无法推断出集合类型,因此必须显式声明 Set
类型。不过,由于 Swift 具备类型推断功能,如果你使用只包含单一类型值的数组字面量来初始化集合,就不必写出集合元素的类型。favoriteGenres
的初始化可以采用更简洁的形式来编写:
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]
由于数组字面量中的所有值都是同一类型,Swift 可以推断出 Set<String>
是 favoriteGenres
变量应使用的正确类型。
访问和修改集合
你可以通过集合的方法和属性来访问和修改它。
要了解集合中元素的数量,可以查看其只读的 count
属性:
print("I have \(favoriteGenres.count) favorite music genres.")
// Prints "I have 3 favorite music genres."
可以使用布尔类型的 isEmpty
属性作为快捷方式,来检查 count
属性的值是否等于 0:
if favoriteGenres.isEmpty {
print("As far as music goes, I'm not picky.")
} else {
print("I have particular music preferences.")
}
// Prints "I have particular music preferences."
插入
favoriteGenres.insert("Jazz")
// favoriteGenres now contains 4 items
你可以通过调用集合的 remove(_:)
方法从集合中移除一个元素。如果该元素是集合的成员,此方法会将其移除并返回被移除的值;如果集合中不包含该元素,则返回 nil
。另外,也可以使用集合的 removeAll()
方法移除集合中的所有元素。
if let removedGenre = favoriteGenres.remove("Rock") {
print("\(removedGenre)? I'm over it.")
} else {
print("I never much cared for that.")
}
// Prints "Rock? I'm over it."
要检查一个集合是否包含某个特定元素,可以使用 contains(_:)
方法。
if favoriteGenres.contains("Funk") {
print("I get up on the good foot.")
} else {
print("It's too funky in here.")
}
// Prints "It's too funky in here."
遍历集合
你可以使用 for-in
循环来遍历集合中的值。
有关 for-in
循环的更多信息,请参阅“for-in
循环”。
Swift 的 Set
类型没有定义特定的顺序。若要按特定顺序遍历集合中的值,可使用 sorted()
方法,该方法会以数组形式返回集合中的元素,数组中的元素按小于运算符(<
)排序。
执行集合操作
你可以高效地执行基本的集合操作,例如将两个集合合并在一起、确定两个集合有哪些共同的值,或者判断两个集合包含的元素是完全相同、部分相同还是完全不同。
基本集合操作
下图展示了两个集合 —— a
和 b
,不同集合操作的结果用阴影区域表示。
执行集合操作
- 使用
intersection(_:)
方法创建一个新集合,新集合仅包含两个原集合中共有的元素。 - 使用
symmetricDifference(_:)
方法创建一个新集合,新集合包含仅存在于其中一个原集合中的元素(即不同时存在于两个集合中的元素)。 - 使用
union(_:)
方法创建一个新集合,新集合包含两个原集合中的所有元素。 - 使用
subtracting(_:)
方法创建一个新集合,新集合包含不在指定集合中的元素。
集合成员关系和相等性
下图展示了三个集合 —— a
、b
和 c
,其中重叠区域表示集合间共享的元素。集合 a
是集合 b
的超集,因为 a
包含了 b
中的所有元素。相反,集合 b
是集合 a
的子集,因为 b
中的所有元素也都包含在 a
中。集合 b
和集合 c
彼此不相交,因为它们没有共同的元素。
集合成员关系和相等性判断方法
- 使用“相等”运算符(
==
)来判断两个集合是否包含完全相同的元素。 - 使用
isSubset(of:)
方法来判断一个集合的所有元素是否都包含在指定集合中。---儿子是否包含在父亲中 - 使用
isSuperset(of:)
方法来判断一个集合是否包含指定集合中的所有元素。 ---父亲是否包含儿子 - 使用
isStrictSubset(of:)
或isStrictSuperset(of:)
方法来判断一个集合是否是指定集合的真子集或真超集(即子集或超集,但不相等)。 - 使用
isDisjoint(with:)
方法来判断两个集合是否没有共同元素。