1. 集合的创建

在前面几期已经介绍过了python中列表[]、元组()和字典{}的创建和使用,这一期要介绍的是另一个相似的结构,也就是哈希集合set(),和python中的哈希表也就是字典相似,集合set()也是用大括号{}来表示的,它可以用下面的方式进行初始化:

1
2
3
4
5
6
7
8
9
10
11
12
nums = {1, 2, 3}
print(nums)

nums = set()
nums.add(1)
nums.add(2)
nums.add(3)
print(nums)

nums = [1, 2, 3]
num_set = set(nums)
print(num_set)

上述三种方式打印的结果都是相同的,如下:

1
2
3
{1, 2, 3}
{1, 2, 3}
{1, 2, 3}

值得注意的是,虽然集合和字典都用{}来表示,但是集合的初始化不能使用num_set = {}这种方式,因为这种方式只会创建出一个字典。

2. 集合的特性

2.1 集合是无序、无法进行索引的、元素不重复的

除此之外,集合中的元素是无序的,因此集合中的元素也无法像列表一样能够通过索引进行访问,集合中也不存在相同的元素,因此当你使用add方法向集合中添加两个相同的元素时,集合中只会保留一个,例如:

1
2
3
4
num_set = set()
num_set.add(1)
num_set.add(1)
print(num_set)

此时的输出结果如下

1
{1}

当我们对一个字符串使用set()函数时,python会将其每个独一无二的字符单独存进集合中,例如

1
2
str_set = set('hello')
print(str_set)

其输出结果如下:

1
{'e', 'o', 'l', 'h'}

可以看到,’hello’中的两’l’最终只保留了一个,并且字符存放顺序也是乱序的,符合上述我们说的集合的特点。

2.2 集合可快速进行成员检查(in操作)

对于列表来说,进行成员检查的时间复杂度为$O(n)$,因为要逐个遍历字典中的每个元素知道找到目标元素,如3 in [1, 2, 3]这样的操作。
对于集合来说,由于集合是基于哈希表实现的,因此其进行成员检查的时间复杂度为$O(1)$,如3 in {1, 2, 3}这样的操作

3. 集合的运算

我们之前已经知道了列表的运算方式,对两个列表做加法运算的结果是将第二个列表直接拼接在第一个列表的后面,对一个列表使用符合’* n’并不是表示对其中的每个元素做乘法运算,乘上一个n,而是将该列表支付n - 1份拼接在原列表后面。列表运算中不存在减法运算。
而对于集合来说,两个集合之间的运算方式共有4中,分别是- | & ^

3.1 集合的 - 运算

两个集合的-运算表示若被减集合中存在减集合中的元素,则将该元素从被减集合中删除,其余元素不变。

1
2
3
4
num_1 = {1, 2, 3}
num_2 = {3, 4, 5}
num = num_1 - num_2
print(num)

输出结果为

1
{1, 2}

因为被减集合中存在与减集合中相同的元素3,因此将其删除,并输出最后的结果。

3.2 集合的 | 运算

两个集合的|运算表示将两个集合做并集。注意集合运算中不存在+运算。

1
2
3
4
num_1 = {1, 2, 3}
num_2 = {3, 4, 5}
num = num_1 | num_2
print(num)

输出结果为

1
{1, 2, 3, 4, 5}

3.3 集合的 & 运算

两个集合的&运算即对两个集合做交集。

1
2
3
4
num_1 = {1, 2, 3}
num_2 = {3, 4, 5}
num = num_1 & num_2
print(num)

输出结果为

1
{3}

3.4 集合的 ^ 运算

两个集合的^运算表示对两个集合做反交集。

1
2
3
4
num_1 = {1, 2, 3}
num_2 = {3, 4, 5}
num = num_1 ^ num_2
print(num)

输出结果为

1
{1, 2, 4, 5}

4. 集合的增、删

4.1 在集合中添加元素(add()方法、update()方法)

使用方法add()可以向集合中添加元素,当添加的元素在集合中已经存在时,则不执行任何操作。使用方法update时需要传入的参数是一个集合,update会将该集合中不同的元素更新进原来的集合。换句话说,方法add()用于更新单个元素,方法update()用于更新集合表示的多个元素,当要用方法update更新单个元素时,要将该元素写成集合的形式,否则会报错。具体操作如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
num_1 = {1, 2, 3}
num_2 = {1, 2, 3}
num_3 = {1, 2, 3}
num_4 = {1, 2, 3}

num_1.add(4)
num_2.add(1)

num_3.update({5})
num_4.update(num_3)

print(num_1)
print(num_2)
print(num_3)
print(num_4)

此时输出的结果为

1
2
3
4
{1, 2, 3, 4}
{1, 2, 3}
{1, 2, 3, 5}
{1, 2, 3, 5}

可以看到,通过方法add()集合num_1中添加了一个不重复的元素4,而集合num_2中的元素则没有发生变化。通过方法update()向集合num_4添加单个元素5时需要写成{5},另一方面,当用update()方法将集合num_3更新进num_4时,仅仅更新了新的元素5

4.2 在集合中删除元素(remove()方法、pop()方法、discard()方法)

使用方法remove()可以移除集合中的指定元素,使用方法pop()则随机移除集合中的一个元素。如下所示:

1
2
3
4
5
6
7
8
9
num_1 = {1, 2, 3}
num_2 = {1, 2, 3}

num_1.remove(1)
pop_num = num_2.pop()

print(num_1)
print(num_2)
print(pop_num)

此时的输出结果为

1
2
3
{2, 3}
{2, 3}
1

使用pop()方法后会放回弹出的元素,而remove()则不会。值得注意的是,当使用remove()方法移除一个集合中不存在的元素会会报错,同样的,当对一个为空的集合使用remove()方法后也会报错。此时可以考虑使用discard()方法,discard()方法的使用与remove()相似,只是当使用discard()方法删除集合中不存在的元素或对一个空集合执行discard()方法时,将不会执行任何操作,并且也不会报错。