1.4 集合
- 集合是无序可变序列,使用一对大括号界定,元素不可重复,同一个集合中每个元素都是唯一的。
- 集合中只能包含数字、字符串、元组等不可变类型(或者说可哈希)的数据,而不能包含列表、字典、集合等可变类型的数据。
1.4.1 集合的创建与删除
- 直接将集合赋值给变量
>>> a = {3,5} #直接把集合赋给变量
>>> a.add(7) #向集合中添加元素,如果集合中有了,则忽略add操作
>>> a
{3, 5, 7}
>>> a = {1,2,3}
>>> a
{1, 2, 3}
>>> a = {(1,2),3}
>>> a
{(1, 2), 3}
>>> a = {[1,2],3}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
列表是不可哈希的~
- 使用set将其他类型数据转换为集合
>>> a_set = set(range(8,14))
>>> a_set
{8, 9, 10, 11, 12, 13}
>>> b_set = set([0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8]) #自动去除重复
>>> b_set
{0, 1, 2, 3, 4, 5, 6, 7, 8}
>>> c_set = set() #空集合
>>> c_set
set()
- 使用del删除整个集合
- 当大括号里面有内容时,type()可以根据括号里面的内容来判断对象类型,但是当括号里面没有内容是,我们应该:
>>> x = {1,2,3}
>>> type(x)
<class 'set'>
>>> x = {1:2,2:3,3:4}
>>> type(x)
<class 'dict'>
>>> x = {1,2,3;4} #要么是字典,要么是集合
File "<stdin>", line 1
x = {1,2,3;4} #要么是字典,要么是集合
^
SyntaxError: invalid syntax
>>> x = {}
>>> type(x)
<class 'dict'>
>>> x = set()
>>> type(x)
<class 'set'>
- 当不再使用某个集合时,可以使用del命令删除整个集合。集合对象的pop()方法删除并返回其中一个元素,remove()方法直接删除指定元素,clear()方法清空集合。
>>> a = {1,4,2,3} #构建一个集合
>>> a.pop() #随机弹出一个元素,因为集合本身就是无序的
1
>>> a.pop()
2
>>> a
{3, 4}
>>> a.add(5) #添加一个元素
>>> a
{3, 4, 5}
>>> a.remove(3) #删除指定元素
>>> a
{4, 5}
1.4.2 集合操作
- Python集合支持交集、并集、差集、对称差集等运算。
>>> a_set = set([8,9,10,11,12,13])
>>> b_set = {0,1,2,3,7,8}
>>> a_set | b_set #并集
{0, 1, 2, 3, 7, 8, 9, 10, 11, 12, 13}
>>> a_set.union(b_set) #并集
{0, 1, 2, 3, 7, 8, 9, 10, 11, 12, 13}
>>> a_set & b_set #交集
{8}
>>> b_set.intersection(a_set) #交集
{8}
>>> b_set.difference(a_set) #差集
{0, 1, 2, 3, 7}
>>> b_set - a_set #差集
{0, 1, 2, 3, 7}
>>> a_set.symmetric_difference(b_set) #对称差集
{0, 1, 2, 3, 7, 9, 10, 11, 12, 13}
>>> a_set ^ b_set #对称差集
{0, 1, 2, 3, 7, 9, 10, 11, 12, 13}
>>> x = {1,2,3}
>>> y = {1,2,5}
>>> z = {1,2,3,4}
>>> x.issubset(y) #测试是否为子集
False
>>> x.issubset(z) #测试是否为子集
True
>>> {3} & {4}
set()
>>> {3}.isdisjoint({4}) #如果两个集合的交集为空,返回True
True
- 集合包含关系测试
>>> x = {1,2,3}
>>> y = {1,2,5}
>>> z = {1,2,3,4}
>>> a = {1,2,5,6}
>>> x < a
False
>>> x < y #比较集合大小/包含关系,如果小于则是真子集,如果小于等于则是子集
False
>>> {1,2,3} < {1,2,3} #子集
False
>>> {1,2} < {1,2,3}
True
>>> {1,2,3} <= {1,2,3}
True
- 使用集合快速提取序列中单一元素
>>> import random
>>> listRandom = [random.choice(range(10000)) for i in range(100)]
>>> norepeat = []
>>> for i in listRandom:
... if i not in norepeat:
... norepeat.append(i)
...
>>> len(listRandom)
100
>>> len(norepeat)
1.4.3 集合运用案例
注:集合里面的元素是靠哈希表来决定他们的顺序,而哈希表的访问速度比较快
- 例2-1 生成不重复随机数的效率比较
(1)
>>> def RandomNumbers(number,start,end):
... #使用列表来生成numberb个介于start和end之间的不重复随机数
... data = []
... n = 0
... while True:
... element = random.randint(start,end)
... if element not in data:
... data.append(element)
... n+=1
... if n == number - 1:
... break
... return data
(2)
>>> def RandomNumbers(number,start,end):
... #使用列表来生成numberb个介于start和end之间的不重复随机数
... data = []
... while True:
... element = random.randint(start,end)
... if element not in data:
... data.append(element)
... if len(data) == number:
... break
... return data
(3)直接定义data为集合类型,将随机元素往里扔,根据集合的元素不可重复特性
>>> def RandomNumbers(number,start,end):
... #使用列表来生成numberb个介于start和end之间的不重复随机数
... data = set()
... while True:
... data.add(random.randint(start,end))
... if len(data) == number:
... break
... return data
综合代码及结果:
import time
import random
def RandomNumbers(number,start,end):
#使用列表来生成numberb个介于start和end之间的不重复随机数
data = []
n = 0
while True:
element = random.randint(start,end)
if element not in data:
data.append(element)
n+=1
if n == number - 1:
break
return data
def RandomNumbers1(number,start,end):
#使用列表来生成numberb个介于start和end之间的不重复随机数
data = []
while True:
element = random.randint(start,end)
if element not in data:
data.append(element)
if len(data) == number:
break
return data
def RandomNumbers2(number,start,end):
#使用列表来生成numberb个介于start和end之间的不重复随机数
data = set()
while True:
data.add(random.randint(start,end))
if len(data) == number:
break
return data
#数字范围
begin,end = 1,10000
#要获取的不重复数字个数
num = 5000
#重复测试次数
rep = 10
for ran in (RandomNumbers,RandomNumbers1,RandomNumbers2):
start = time.time()
for i in range(rep):
ran(num,begin,end)
print(ran.__name__,time.time()-start)
== RESTART: C:/Users/91908/AppData/Local/Programs/Python/Python37/test4.py ==
RandomNumbers 12.100703001022339
RandomNumbers1 12.142316102981567
RandomNumbers2 0.46073246002197266
注:为什么第二个方法比第一个方法略慢一些,因为第二个方法每循环一次都要计算一次列表的长度
1.4.4 集合推导式
>>> s = {x.strip() for x in (' he ','she ',' I')} #strip()是用来清楚空格的
>>> s
{'she', 'he', 'I'}