python基础——数据类型(六)集合
本文最后更新于:1 年前
¶(一)概述:
集合set是一个无序的唯一确定元素序列。
无序代表着其每次输出时元素的排列顺序可能都不相同。
唯一确定意味着元素是不可重复的,且每个元素互不相同。
元素的个数无限制。
set是可变数据类型,其内容是可以改变的,因此set没有哈希值,不能被用作字典的键或是其他集合的元素。
同一集合中,只能存储不可变的数据类型,不能再存储列表、set集合、字典等可变数据类型元素,因此set集合没有多维形式。(代码见(二)内代码)
¶(二)创建与形式:
python用{}大括号表示set集合,并用逗号分隔元素。
形式为: setname = { element1 , element2 , ... , elementn }
注意:set没有直接的空集合创建形式。因为直接用{}创建表示的是空字典,而不是空列表,此时应使用***set()***表示空集合。
set创建时若有重复元素,只保留其中一个。(备注:列表去除重复元素最迅速的方法就是转为集合,其运行时间远小于其他去重方法)
set集合内的bool值True不会被创建,只有False才会被创建(不知道为什么)。
1 |
|
¶(三)集合的特性:
¶1. 访问元素:
set集合因其无序,没有索引和下标,一般情况下访问元素只能通过遍历和枚举逐一读取(枚举中会有索引值,但不意味着set有索引)。
遍历一般会使用in关键字。
1 |
|
¶2. 删除集合
python自带垃圾回收机制,已创建的集合如不再使用,将会被编译器自动回收,不会产生内存垃圾。
如果需要可以手动删除,使用del 关键字手动删除集合。
形式为: del setname
1 |
|
¶3. 集合的关系:
-
判断子集关系:
-
使用关系运算符< 、<=、>、>=(用rop指代):
形式:setname1 rop setname2
返回True或者False
当rop为<=,表示子集判断,即当setname1中元素均在setname2中出现时,表示集合1为集合2子集,返回True;否则返回False。
当rop为<,表示真子集判断,即当setname1中元素均在setname2中出现且setname2有setname1中没有的元素时,表示集合1为集合2真子集,返回True,否则均返回False。
>=和>的逻辑和前两者相同,但是setname1和setname2的地位互换,表示setname1对setname2的包含和真包含关系。
-
使用方法:
-
issubset方法:
形式:setname1.issubset(setname2)
与setname1<=setname2等价。
-
issuperset方法:
形式:setname1.issuperset(setname2)
与setname>=setname2等价。
-
1
2
3
4
5
6
7
8
9
10
11a = {1,2,3,4,5,6}
b = {1,2,3,4}
c = {1,2,3,4,5,6}
print(b<a,b>a,b<=a,b>=a,sep="\t")
print(c<a,c>a,c<=a,c>=a,sep="\t")
print(b.issubset(a),c.issubset(a),sep="\t")
print(b.issuperset(a),c.issuperset(a),sep="\t")
# True False True False
# False False True True
# True True
# False True -
-
集合运算方法:
-
交集运算:
形式:setname1&setname2 / setname1.intersection(setname2)
两个集合可以交换位置,生成结果相同。
生成一个新集合获得两个集合的所有公共元素。
可以进行多个集合的连续交运算。
1
2
3
4
5
6
7
8
9
10
11
12
13
14a={1,2,3,4,5}
b={3,4,5,6,7}
c={1,2,3,5,6,7}
print(a&b)
print(a.intersection(b))
print(b.intersection(a))
print(a&b&c)
print(c.intersection(a,b))
# 运行结果:
# {3, 4, 5}
# {3, 4, 5}
# {3, 4, 5}
# {3, 5}
# {3, 5} -
并集运算:
形式:setname1 | setname2 / setname1.union(setname2)
两个集合可以交换位置,生成结果相同。
生成一个新集合获得两个集合的所有元素,且不重复。
可以进行多个集合的连续并运算。
1
2
3
4
5
6
7
8
9
10
11
12
13
14a={1,2,3,4,5}
b={3,4,5,6,7}
c={1,2,3,5,6,7,8,9}
print(a|b)
print(a.union(b))
print(b.union(a))
print(a|b|c)
print(c.union(a,b))
# 运行结果:
# {1, 2, 3, 4, 5, 6, 7}
# {1, 2, 3, 4, 5, 6, 7}
# {1, 2, 3, 4, 5, 6, 7}
# {1, 2, 3, 4, 5, 6, 7, 8, 9}
# {1, 2, 3, 4, 5, 6, 7, 8, 9} -
差集运算:
形式:setname1 - setname2 / setname1.difference(setname2)
两个集合可以交换位置,但是生成结果会不同。
生成一个集合获得setname1中所有不在setname2中出现的元素,即新集合和setname2的交集一定为空集。
可以进行多个集合的差集运算,得到的是该集合去除其他所有集合含有元素之后的剩余元素。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16a={1,2,3,4,5}
b={3,4,5,6,7}
c={1,2,3,5,6,7,8,9}
print(a-b)
print(b-a)
print(a.difference(b))
print(b.difference(a))
print(c-a-b)
print(c.difference(a,b))
# 运行结果:
# {1, 2}
# {6, 7}
# {1, 2}
# {6, 7}
# {8, 9}
# {8, 9} -
对称差集运算:
形式:setname1 ^ setname2 / setname1.symmetric_difference(setname2)
两个集合可以交换位置,生成结果相同。
生成一个集合获得setname1和setname2中不同时出现的元素,即新集合和两个集合的交集的交集一定为空集。
只能进行多个集合的连续对称差集运算,不能做同时的对称差集运算(也就是每次的运算对象只能有两个)。
1
2
3
4
5
6
7
8
9
10
11
12a={1,2,3,4,5}
b={3,4,5,6,7}
c={1,2,3,5,6,7,8,9}
print(a^b)
print(a.symmetric_difference(b))
print(a^b^c)
print(c.symmetric_difference(a.symmetric_difference(b))) #不允许在symmetric_difference方法中加入多个参数。
# 运行结果:
# {1, 2, 6, 7}
# {1, 2, 6, 7}
# {3, 5, 8, 9}
# {3, 5, 8, 9}
-
-
判断相交方法:
形式: setname1.isdisjoint(setname2)
两个集合可以交换位置,生成结果相同。
两个集合交集为空时返回False,否则返回True(此时有公共元素)。
不允许连续集合相交判断或者多个集合同时相交判断。
1
2
3
4
5
6
7
8a={1,2,3,4,5}
b={3,4,5,6,7}
c={6,7,8,9}
print(a.isdisjoint(b))
print(a.isdisjoint(c)) #isdisjoint方法只接受一个参数
# 运算结果:
# False
# True
¶4. 集合的增删改查:
-
向set集合添加元素:
set集合不支持重复和连接操作(也就是"+"和"*"运算符)。
-
add方法:
形式:setname.add(element)
只向set集合添加一个元素,只允许添加不可变类型。
添加已有元素不对集合进行任何操作。
1
2
3
4
5
6a={1,2,3,4,5}
a.add(6)
a.add(1)
print(a)
# 运行结果:
# {1, 2, 3, 4, 5, 6} -
update方法:
形式:setname.update(elements)
向set集合中添加传入update的一系列元素,只允许添加不可变类型。
添加已有元素不对集合进行任何操作。
update一般是传入另一个集合,会将其所有非公共元素分别加入setname中。
可以传入非集合的一系列字符串。
1
2
3
4
5
6
7
8a={1,2,3,4,5}
b={3,4,5,6,7}
a.update(b)
a.update("a","b","c")
a.update()
print(a)
# 运行结果:
# {1, 2, 3, 4, 5, 6, 7, 'a', 'b', 'c'} -
交/差/对称差更新:
在其相关方法后加_update,不会返回新集合,而是直接将原集合替换为运算结果。(详细方法略,有兴趣请了解difference_update、intersection_update等函数)
-
-
删除set集合元素:
-
pop方法:
形式:setname.pop()
pop方法从集合中移除并返回一个元素,此元素的选择是随机的。
注意:如果有一系列数字,从0开始删除,不是完全随机的。
1
2
3
4
5
6
7
8
9
10
11
12
13a={"a",3,1,2,5,6,4,0}
b={"我","你","她"}
print(a.pop())
print(a.pop())
print(a)
print(b.pop())
print(b)
# 运行结果:
# 0
# 1
# {2, 3, 'a', 5, 6, 4}
# 你
# {'她', '我'}、 -
remove方法:
形式:setname.remove(element)
从集合中移除指定元素,如果该元素不存在会引发KeyError错误。
1
2
3
4
5
6
7a={1,2,3,4,5,6}
a.remove(1)
a.remove(2)
# a.remove(7) 此句会报错
print(a)
# 运行结果:
# {3, 4, 5, 6} -
discard方法:
形式:setname.discard(element)
和remove要求相同,但是在删除不存在元素时不会报错。
1
2
3
4
5
6
7a={1,2,3,4,5,6}
a.discard(1)
a.discard(2)
a.discard(7)
print(a)
# 运行结果:
# {3, 4, 5, 6} -
clear方法:
形式:setname.discard()
清空元素
1
2
3
4
5a={1,2,3,4,5,6}
a.clear()
print(a)
# 运行结果:
# set()
-
-
查询set集合元素
not in和in关键字。
使用形式不在赘述
注意:集合的查询时间是θ(1),而列表的时间是θ(n)。
¶5.集合的其他操作:
内置函数:
-
len()求集合长度(即元素数量)。
-
max()求集合内元素最大值。
-
min()求集合内元素最小值。
-
sum()求集合元素之和(如果可以求出的话)。
集合的复制:
集合的复制一般不考虑深浅拷贝。
-
直接赋值:
= 直接赋值是非拷贝方法。
两个集合是等价的,修改其中任何一个集合都会影响另一个集合。(代码略)
-
集合推导式:
形式:setname1 = { i for i in setname2 }
利用推导式完成复制。
1
2
3
4
5a={1,2,3,4,5,6}
b={i for i in a if i!=1}
print(b)
# 输出结果:
# {2, 3, 4, 5, 6} -
for循环:略
-
copy方法:
形式:setname1=setname2.copy()
1
2
3
4
5a={1,2,3,4,5,6}
b=a.copy()
print(b)
# 输出结果:
# {1, 2, 3, 4, 5, 6} -
deepcopy方法:
格式:setname1= copy.deepcopy(setname2)
需要import copy库:
1
2
3
4
5
6import copy
a={1,2,3,4,5,6}
b=copy.deepcopy(a)
print(b)
# 输出结果:
# {1, 2, 3, 4, 5, 6}
排序:
sorted函数排序:略(有需要请看前面的内容)。
¶(四)不可变集合frozenset :
和set相关,是不可变的,且为hashable,其元素一经创建无法更改。
可以用作字典的键或者其他集合的元素。
set中所有改变集合本身的方法都不支持(如add、remove方法等等),其余的方法都支持。
和set进行集合运算时,返回类型为运算左侧对象对应的类型。
如果set需要不可变就用frozenset来代替。
由元素创建时,frozenset必须由强制转化指定类型。
1 |
|