如有兴趣了解更多请关注我的个人博客https://07xiaohei.com/
(一)概述:
集合set是一个无序的唯一确定元素序列。
无序代表着其每次输出时元素的排列顺序可能都不相同。
唯一确定意味着元素是不可重复的,且每个元素互不相同。
元素的个数无限制。
set是可变数据类型,其内容是可以改变的,因此set没有哈希值,不能被用作字典的键或是其他集合的元素。
同一集合中,只能存储不可变的数据类型,不能再存储列表、set集合、字典等可变数据类型元素,因此set集合没有多维形式。(代码见(二)内代码)
(二)创建与形式:
python用{}大括号表示set集合,并用逗号分隔元素。
形式为: setname = { element1 , element2 , … , elementn }
注意:set没有直接的空集合创建形式。因为直接用{}创建表示的是空字典,而不是空列表,此时应使用***set()***表示空集合。
set创建时若有重复元素,只保留其中一个。(备注:列表去除重复元素最迅速的方法就是转为集合,其运行时间远小于其他去重方法)
set集合内的bool值True不会被创建,只有False才会被创建(不知道为什么)。
a = {1 , "a" , 3.14 , True }
b = {}
bb = set()
c = {1 , 1 , "a" , "a" , 3.14 , 3.14 , False , True}
# d = {[1,2,3],1,2,3} 此句会运行失败,因为不允许在set集合内创建列表。
print(a)
print(type(a))
print(type(b))
print(type(bb))
print(c)
# 运行结果:
# {'a', 1, 3.14}
# <class 'set'>
# <class 'dict'>
# <class 'set'>
# {'a', 1, 3.14, False}
(三)集合的特性:
1. 访问元素:
set集合因其无序,没有索引和下标,一般情况下访问元素只能通过遍历和枚举逐一读取(枚举中会有索引值,但不意味着set有索引)。
遍历一般会使用in关键字。
a = {1,2,3,4,True,"a","b","c","d"}
for i,v in enumerate(a):
print(i," ",v,end="\n")
for i in a:
print(i,end=" ")
# 运行结果:
# 0 1
# 1 2
# 2 3
# 3 4
# 4 d
# 5 a
# 6 b
# 7 c
# 1 2 3 4 d a b c
2. 删除集合
python自带垃圾回收机制,已创建的集合如不再使用,将会被编译器自动回收,不会产生内存垃圾。
如果需要可以手动删除,使用del 关键字手动删除集合。
形式为: del setname
a={1,2,3,4,5}
del a
print(a) #此句无法输出,因为a已经被删除了,a变量处于未定义状态
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等价。
-
a = {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)
两个集合可以交换位置,生成结果相同。
生成一个新集合获得两个集合的所有公共元素。
可以进行多个集合的连续交运算。
a={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)
两个集合可以交换位置,生成结果相同。
生成一个新集合获得两个集合的所有元素,且不重复。
可以进行多个集合的连续并运算。
a={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的交集一定为空集。
可以进行多个集合的差集运算,得到的是该集合去除其他所有集合含有元素之后的剩余元素。
a={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中不同时出现的元素,即新集合和两个集合的交集的交集一定为空集。
只能进行多个集合的连续对称差集运算,不能做同时的对称差集运算(也就是每次的运算对象只能有两个)。
a={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(此时有公共元素)。
不允许连续集合相交判断或者多个集合同时相交判断。
a={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集合添加一个元素,只允许添加不可变类型。
添加已有元素不对集合进行任何操作。
a={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中。
可以传入非集合的一系列字符串。
a={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开始删除,不是完全随机的。
a={"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错误。
a={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要求相同,但是在删除不存在元素时不会报错。
a={1,2,3,4,5,6} a.discard(1) a.discard(2) a.discard(7) print(a) # 运行结果: # {3, 4, 5, 6}
-
clear方法:
形式:setname.discard()
清空元素
a={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 }
利用推导式完成复制。
a={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()
a={1,2,3,4,5,6} b=a.copy() print(b) # 输出结果: # {1, 2, 3, 4, 5, 6}
-
deepcopy方法:
格式:setname1= copy.deepcopy(setname2)
需要import copy库:
import 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必须由强制转化指定类型。
a=frozenset({1,2,3,4,5,6}) #由强制转化创建
b={4,5,6,7,8,9} #可变
print(type(a&b))
print(type(b&a)) #和右边类型相同
a.issubset(b) #支持不改变集合的set的所用方法
# a.remove(1) 此句报错,frozenset没有改变元素的方法
# 输出结果
# <class 'frozenset'>
# <class 'set'>