Swift 集合(Set)

在本教程中,您将了解集合,创建集合,修改集合以及集合中的一些常见操作。

在上一篇Swift 数组文章中,我们了解了如何创建可以在一个有序列表中包含多个值的数组。

但是,如果我们要确保列表只能唯一值,那么我们使用Swift中的set(集合)。

什么是集合?

集合只是一个容器,可以在无序列表中保存多个数据类型的值,并确保容器中的元素唯一(即每个数据仅出现一次)。

无序列表意味着您将无法按照定义集合中的项的顺序获得元素。

使用集合而不是数组的主要优点是,当您需要确保一个项只出现一次,并且项的顺序并不重要时。

存储在集合中的值必须是散列的。这意味着它必须提供hashValue属性。这一点很重要,因为集合是无序的,它使用hashValue来访问集合的元素。

默认情况下,Swift的所有基本类型(如String、Int、Double和Bool)都是可散列的,并且可以用作设置值类型。但是,您也可以在Swift中创建可以存储在集合中的散列类型。

如何在Swift中声明集合?

通过将类型指定为set,然后指定它可以存储在<>中的数据类型,也可以创建空集。

示例1:声明一个空集

let emptyIntSet:Set= []
print(emptyIntSet)

或者

let emptyIntSet:Set= Set()
print(emptyIntSet)

运行该程序时,输出为:

[ ]

在上面的程序中,我们声明了一个Set 类型常量 emptyInt ,该常量集合 可以存储多个整数值并使用0值初始化。

由于Swift是一种类型推断语言,因此您也可以不指定数据类型而直接创建 set 集合,但是必须使用一些值进行初始化,以便编译器可以将其类型推断为:

示例2:声明具有某些值的集合

let someIntSet:Set = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(someIntSet)

运行该程序时,输出为:

[2, 4, 9, 5, 6, 7, 3, 1, 8]

在上面的程序中,我们声明了一个常量 someIntSet,该常量可以存储 Integer 集,而无需显式指定类型。但是,我们需要在定义变量时带上 :Set,否则Swift将为我们创建一个数组。

此外,作为数组,我们使用[]括号用 1、2、3、4、5、6、7、8、9 值初始化了集合。

您已经知道,当您尝试使用 print(someIntSet) 将集合中的值打印输出时,你会得到一个不同的顺序,不同于在集合中您已经定义的项目顺序,因为它存储值没有定义的顺序。因此,每次访问顺序时都会发生变化。

示例3:声明具有重复值的集合

let someStrSet:Set = ["ab","bc","cd","de","ab"]
print(someStrSet)

运行该程序时,输出为:

["de", "ab", "cd", "bc"]

你已经知道,当你试图打印集合内的值作为打印(someIntSet) ,在上面的程序中,我们在集合中定义了一个重复值 ab。还有。当我们尝试使用 print (someStrSet)访问集合内的值时,重复值将自动从集合中删除。因此,set 保证其中的唯一元素/值。

您还可以在Swift中使用自己的自定义 Hashable 类型声明一个集合。

如何在Swift中访问set元素?

不能使用下标语法作为数组访问集合的元素。 这是因为集合是无序的,并且没有访问元素的索引。
所以,您需要使用其方法和属性 或 使用for-in循环来访问集合。

示例4:for...in访问集合中的元素

var someStrSet:Set = ["ab", "bc", "cd", "de"]
for val in someStrSet {
    print(val)
}

运行该程序时,输出为:

de
ab
cd
bc

在上面的程序中,我们得到的val与集合中元素的顺序不同,因为集合与数组不同,它们是无序的。

您还可以访问集合的元素,直接从集合中移除值,如下所示:

示例5:使用remove()访问集合中的元素

var someStrSet:Set = ["ab", "bc", "cd", "de"]
let someVal = someStrSet.remove("cd")
print(someVal)
print(someStrSet)

运行该程序时,输出为:

Optional("cd")
["de", "ab", "bc"]

在上面的程序中,您可以看到 remove方法返回一个可选字符串。因此,建议您执行以下可选处理。要了解有关可选的更多信息,请访问Swift 可选

示例6:remove()的可选处理

var someStrSet:Set = ["ab", "bc", "cd", "de"]
if let someVal = someStrSet.remove("cd") {
    print(someVal)
    print(someStrSet)
} else {
    print("cannot find element to remove")
}

运行该程序时,输出为:

cd
["de", "ab", "bc"]

如何在集合中添加新元素?

您可以使用Swift中的 insert() 方法将新元素添加到集合中。

示例7:使用insert()添加新元素

var someStrSet:Set = ["ab", "bc", "cd", "de"]
someStrSet.insert("ef")
print(someStrSet)

运行该程序时,输出为:

["ab", "de", "cd", "ef", "bc"]

在上面的程序中,我们使用集合的insert()方法向集合添加新元素。由于集合是无序的,因此插入元素的位置是未知的。

集合的操作

使用集合的另一个主要优点是可以执行集合操作,例如将两个集合组合在一起、确定两个集合具有哪些共同的值等。这些操作类似于数学中的集合操作。

在Swift中设置操作

1.并集

两个集合a和b的并集是在a或b中 或 在a和b两者中的元素的集合。

let a: Set = [1, 3, 5, 7, 9]
let b: Set = [0, 2, 4, 6, 8]
print(a.union(b))

当您运行上述程序时,输出将是:

[8, 2, 9, 4, 5, 7, 6, 3, 1, 0]

2.交集

两个集合a和b的交集是包含a的所有元素的集合,这些元素同时也属于b。

let a: Set = [1, 3, 5, 7, 9]
let b: Set = [0, 3, 7, 6, 8]
print(a.intersection(b))

当您运行上述程序时,输出将是:

[7, 3]

因此,print(a.intersection(b))输出一个新的集合,其值 [7、3] 在 a 和 b 集合中都存在。

3.差集

两个集合a和b的差集,它包含 a 的所有元素,但去掉同样属于 b 的元素。

let a: Set = [1, 3, 5, 7, 9]
let b: Set = [0, 3, 7, 6, 8]
print(a.subtracting(b))

当您运行上述程序时,输出将是:

[5, 9, 1]

因此,print(a.subtracting(b)) 输出具有值[ 5,9,1] 的新集合。

4.对称差集

两个集合a和b的对称差是包含所有元素的集合,这些元素位于两个集合中的任何一个中,但不同时存在两个集合中。

let a: Set = [1, 3, 5, 7, 9]
let b: Set = [0, 3, 7, 6, 8]
print(a.symmetricDifference(b))

当您运行上述程序时,输出将是:

[5, 6, 8, 0, 1, 9]

因此,print(a.symmetricDifference(b)) 输出具有值[ 5、6、8、0、1、9] 的新集合。

集合成员关系和相等运算

集合相等

您可以使用 == 运算符检查两个集合是否包含相同的元素。如果两个集合包含相同的元素,则返回true,否则返回false。

示例5:集合相等操作

let a: Set = [1, 3, 5, 7, 9]
let b: Set = [0, 3, 7, 6, 8]
let c:Set = [9, 7, 3, 1, 5]

if a == b {
    print("a和b相同")
} else {
    print("a和b不同")
}

if a == c {
    print("a和c相同")
} else {
    print("a和c不同")
}

当您运行上述程序时,输出将是:

a和b不同
a和c相同

集合成员关系

您还可以使用以下方法检查两个集合之间的关系:

  • isSubset(of:) - 此方法确定一个集合的所有值是否都存在于指定的集合中。

  • isSuperset(of:)  - 此方法确定集合是否包含指定集合中的所有值。

  • isStrictSubset(of:)或 isStrictSuperset(of:): - 此方法确定一个集合是指定集合的子集还是超集,但不等于指定集合。

  • isDisjoint(with:)  - 此方法确定两个集合是否没有共同的值。

示例6:集合成员关系操作

let a: Set = [1, 3, 5, 7, 9]
let b: Set = [0, 3, 1, 7, 6, 8, 9, 5]

print("isSubset:", a.isSubset(of: b))
print("isSuperset:", b.isSuperset(of: a))
print("isStrictSubset:", a.isStrictSubset(of: b))
print("isDisjointWith:", a.isDisjoint(with: b))

当您运行上述程序时,输出将是:

isSubset: true
isSuperset: true
isStrictSubset: true
isDisjointWith: false

让我们分析下面的print语句中使用的方法:

  • isSubset返回 true,因为集合b包含a中的所有元素

  • isSuperset返回true,因为b包含a的所有值。

  • isStrictSubset返回true,因为集合b包含a中的所有元素,并且两个集合不相等。

  • isDisjointWithreturns 返回 false,因为a和b具有一些共同的值。

集合内置函数和属性

1. isEmpty 属性

此属性确定集合是否为空。如果集合不包含任何值,它返回true,否则返回false。

示例7:isEmpty如何工作?

let intSet:Set = [21, 34, 54, 12]
print(intSet.isEmpty)

运行该程序时,输出为:

false

2.first 属性

此属性用于访问集合的第一个元素。

示例8:first如何工作?

let intSet = [21, 34, 54, 12]
print(intSet.first)

运行该程序时,输出为:

Optional(54)

由于Set是无序集合,因此 first 属性并不能保证是该集合的第一个元素。 您很有可能会得到54以外的其他值。

同样,您可以使用 last 属性来访问集合的最后一个元素。

3.insert 函数 - 插入元素

insert函数用于在集合中插入/追加元素。

示例9:insert函数如何工作?

var intSet:Set = [21, 34, 54, 12]
intSet.insert(50)
print(intSet)

运行该程序时,输出为:

[54, 12, 50, 21, 34]

4.reversed() - 反转集合

此函数以相反的顺序返回集合的元素。

示例10:reversed()如何工作?

var intSet:Set = [21, 22, 23, 24, 25]
print(intSet)
let reversedSet = intSet.reversed()
print(reversedSet)

运行该程序时,输出为:

[22, 23, 21, 24, 25]
[25, 24, 21, 23, 22]

5.count - 返回集合中元素的总数

此属性返回集合中元素的总数。

示例11:count 计数如何工作?

let floatSet:Set = [10.2, 21.3, 32.0, 41.3]
print(floatSet.count)

运行该程序时,输出为:

4

6. removeFirst - 移除并返回集合中第一个值

此函数从集合中删除并返回第一个值。

示例12:removeFirst如何工作?

var strSet:Set = ["ab", "bc", "cd", "de"]
let removedVal = strSet.removeFirst()
print("removed value is \(removedVal)")
print(strSet)

运行该程序时,输出为:

removed value is de
["ab", "cd", "bc"]

同样,您也可以使用 removeAll 函数来清空集合。