注:该学习笔记是根据曾志贤老师编写的《从Excel到Python,用Python轻松处理Excel数据》所学习整理的笔记。
第八章 集合类型处理技术
在Python中,集合是一个无序的不重复元素序列,元素被放在{ }中,是可迭代的,不支持任何索引或切片操作。与列表相比,集合的主要优点是具有高度优化的方法,可以检查集合中是否包含特定元素,也可以进行并集、交集、差集、比较等操作。
目录
一、集合的创建与删除
frozenset函数的参数不一定是可变集合,可以是任何可迭代对象。
set1=set();print(set1) #创建空集合
set2={1,2,3};print(set2) #创建有元素的集合
set3=frozenset(set2);print(set3) #转换为不可变集合
del set1 #删除指定集合
二、集合元素的添加与删除
1、集合元素的添加
向集合中添加单个元素或多个元素,可以使用add函数或update函数。
update函数的参数可以是任何可迭代对象。
set1={1,2,3} #原集合
set1.add(4);print(set1) #向集合中添加单个元素
set1.update({5,6,7});print(set1) #向集合中添加多个元素
注意:如果集合中的所有元素都是数字,则这些数字会按照从小到大的顺序排列,否则排列顺序是混乱的。
2、集合元素的删除
删除集合中的元素可以使用remove、discard、pop、clear函数,根据不同的要求使用不同的函数。
set1={'a','b','c','d'} #原集合
set1.remove('a');print(set1) #删除集合中的元素'a'
set1.discard('b');print(set1) #删除集合中的元素'b'
set1.pop();print(set1) #随机删除集合中的一个元素
set1.clear();print(set1) #清空集合中的所有元素
案例一、多列求唯一值
求销售产品的名单
import xlrd
from xlutils.copy import copy
wb=xlrd.open_workbook('8-2-1.xls')
ws=wb.sheet_by_name('采购表')
nwb=copy(wb)
nws=nwb.add_sheet('提取结果')
nws.write(0,0,'序号')
nws.write(0,1,'名称')
nws.write(0,2,'合计')
num=0
set1=set()
dic={}
for col_num in range(1,ws.ncols,3): #循环最大列,步长3
col_name=ws.col_values(col_num)[1:] #提取整列数据
set1.update(col_name) #放入集合
for row_num in range(1,ws.nrows): #循环最大行
name=ws.cell_value(row_num,col_num) #提取循环列的每一行的值
val=ws.cell_value(row_num,col_num+1) #提取循环列+1的每一行的值
if not name in dic: #判断字典中是否存在key
dic[name]=[val] #不存在则把值赋给key
else:
dic[name].append(val) #存在则把值新增到key
for key,item in tuple(dic.items()): #把字典放入循环
for set_name in set1: #把集合放入循环
if set_name == key: #判断集合的值等于字典的key时
num +=1
nws.write(num,0,num)
nws.write(num,1,set_name)
nws.write(num,2,sum(item))
nwb.save('8-2-1-1.xls')
三、集合之间的大小比较
1、集合的比较运算
print(2 in {1,2,3}) #判断2是否包含在集合中
print({1,2,3}=={3,2,1}) #判断两个集合是否相同
print({2,3}>{1,2,3}) #集合大于比较
print({2,3}<{1,2,3}) #集合小于比较
案例一、判断指定的多个等级是否存在
要求:判断1~4季度每个人包含“优”和“良”两个等级的人有哪些。
import xlrd
from xlutils.copy import copy
wb=xlrd.open_workbook('8-3-1.xls')
ws=wb.sheet_by_name('评级表')
nwb=copy(wb)
nws=nwb.get_sheet('评级表')
for row_num in range(1,ws.nrows):
set1 = set()
set1.update(ws.row_values(row_num)[1:-1])
if {'优','良'} <= set1:
nws.write(row_num,ws.ncols-1,'√')
else:
nws.write(row_num,ws.ncols-1,'×')
nwb.save('8-3-1-1.xls')
四、集合的转换
将可迭代对象转换为集合,除使用集合推导式外,还可以说那个set类,这种方式更直接、简单。
1、类对象转换set
语法结构:
set([iterable])
参数说明:
- iterable:可选参数,要转换为集合的可迭代序列。
set1=set('123');print(set1) #将字符串转换为集合
set2=set([1,2,3]);print(set2) #将列表转换为集合
set3=set((1,2,3));print(set3) #将元组转换为集合
set4=set({'a':1,'b':2,'c':3});print(set4) #将字典的key转换为集合
set5=set(range(1,4));print(set5) #将可迭代对象转换为集合,range只是可迭代对象中的一种
案例一、获取每个工作表中不重复的名单
import xlrd
from xlutils.copy import copy
wb=xlrd.open_workbook('8-4-1.xls')
nwb=copy(wb)
nws=nwb.add_sheet('统计结果')
nws.write(0,0,'年份')
nws.write(0,1,'名单')
num = 0
for ws in wb.sheets(): #遍历工作表
set1 = set()
name=ws.name #获取工作表名
set1.update(ws.col_values(1)[1:]) #获取名字列放入集合
num +=1
nws.write(num,0,name)
nws.write(num,1,'、'.join(set1)) #使用“、”分隔符合并集合中的元素
nwb.save('8-4-1-1.xls')
五、集合的运算
在Python中,集合之间可以做关系运算,例如做并集、交集、差集及对称差集运算。
1、并集运算
并集运算指两个或更多集合合并,结果中包含了所有集合的元素,重复的元素只会出现一次。
并集运算使用union函数或者使用“|”符号。
set1={1,2,3,4,5,6} #集合1
set2={4,5,6,7,8,9} #集合2
set3=set1.union(set2);print(set3) #集合1与集合2进行并集运算
set4=set2.union(set1);print(set4) #集合2与集合1进行并集运算
set5=set1|set2;print(set5) #使用简写符号“|”进行并集运算
set6=set2|set1;print(set6)
2、交集运算
交集运算求两个或更多集合中都包含的元素。
交集运算使用intersection函数或者使用“&”符号。使用intersection_update函数,可将计算结果存储给原有的其中一个集合。
set1={1,2,3,4,5,6} #集合1
set2={4,5,6,7,8,9} #集合2
set3=set1.intersection(set2);print(set3) #集合1与集合2交集,结果写入集合3
set4=set2.intersection(set1);print(set4) #集合2与集合1交集,结果写入集合4
set5=set1&set2;print(set5) #使用简写字符“&”进行交集运算
set6=set2&set1;print(set6)
set1={1,2,3,4,5,6} #集合1
set2={4,5,6,7,8,9} #集合2
set1.intersection_update(set2);print(set1) #集合1与集合2交集,结果写入集合1
set2.intersection_update(set1);print(set2) #集合2与集合1交集,结果写入集合2
3、差集运算
差集运算就是两个集合相减,用一个集合中的元素减去另一个集合中的元素。
差集运算使用difference函数或者使用“-”符号。使用difference_update函数,可将计算结果存储给原有的其中一个集合。
set1={1,2,3,4,5,6} #集合1
set2={4,5,6,7,8,9} #集合2
set3=set1.difference(set2);print(set3) #集合1减集合2,结果写入结合3
set4=set2.difference(set1);print(set4) #集合2减集合1,结果写入结合4
set5=set1-set2;print(set5) #使用简写字符“-”进行差集运算
set6=set2-set1;print(set6)
set1={1,2,3,4,5,6} #集合1
set2={4,5,6,7,8,9} #集合2
set1.difference_update(set2);print(set1) #集合1减集合2,结果写入集合1
set2.difference_update(set1);print(set2) #集合2减集合1,结果写入集合2
4、对称差集运算
对称差集运算返回两个集合中不重复的元素集合,即移除两个集合中都存在的元素。
对称差集运算使用symmetric_difference函数或者使用“^”符号。使用symmetric_difference_update函数,可将计算结果存储给原有的其中一个集合。
set1={1,2,3,4,5,6} #集合1
set2={4,5,6,7,8,9} #集合2
set3=set1.symmetric_difference(set2)
print(set3) #减去集合1与集合2中相同的元素,结果写入集合3
set4=set2.symmetric_difference(set1)
print(set4) #减去集合2与集合1中相同的元素,结果写入集合3
set5=set1^set2;print(set5) #使用简写字符“^”进行对称差集运算
set6=set2^set1;print(set6)
set1={1,2,3,4,5,6} #集合1
set2={4,5,6,7,8,9} #集合2
set1.symmetric_difference_update(set2)
print(set1) #减去集合1与集合2中相同的元素,结果写入集合1
set2.symmetric_difference_update(set1)
print(set2) #减去集合2与集合1中相同的元素,结果写入集合2
5、集合运算小结
使用函数方法与使用符号方法的区别:
- 使用函数方法:则函数的参数不一定是集合类型,只要是可迭代对象即可。
- 使用符号方法:两侧必须是集合类型,否则会出错。
六、集合运算应用案例
案例一、多表多列求唯一值
import xlrd
from xlutils.copy import copy
wb=xlrd.open_workbook('8-6-1.xls')
nwb=copy(wb)
nws=nwb.add_sheet('统计结果')
nws.write(0,0,'公司名')
nws.write(0,1,'名单')
num=0
set1=set()
for ws in wb.sheets(): #遍历所有工作表
name=ws.name
for row_num in range(1,ws.nrows): #循环所有行
val=ws.row_values(row_num)[1:]
set1.update(val) #提取的值写入集合
num +=1
nws.write(num,0,name)
nws.write(num,1,'、'.join(set1)) #按照“、”分隔符组合集合内的元素
set1=set() #清空集合
nwb.save('8-6-1-1.xls')
案例二、多列求相同值
import xlrd
from xlutils.copy import copy
wb=xlrd.open_workbook('8-6-2.xls')
ws=wb.sheet_by_name('优秀员工名单表')
nwb=copy(wb)
nws=nwb.add_sheet('全年优秀表')
nws.write(0,0,'序号')
nws.write(0,1,'姓名')
row_num=0
set1=set(ws.col_values(1)[1:]) #将B列放入集合
set2=set()
for col_num in range(1,ws.ncols): #遍历所有列
set2.update(ws.col_values(col_num)[1:]) #将循环的列放入set2集合
set1.intersection_update(set2) #set1集合与set2集合进行交集
set2=set() #清空set2集合
for name in set1: #遍历交集完的set1集合
row_num +=1
nws.write(row_num,0,row_num)
nws.write(row_num,1,name)
nwb.save('8-6-2-1.xls')
案例三、根据达标月份获取不达标月份
import xlrd
from xlutils.copy import copy
wb=xlrd.open_workbook('8-6-3.xls')
ws=wb.sheet_by_name('达标表')
nwb=copy(wb)
nws=nwb.add_sheet('未达标表',cell_overwrite_ok=True)
#xlwt库默认不能覆盖单元格写入,需在新建工作表时写入“cell_overwrite_ok=True”
dic={}
val_num=set()
row_num=0
for name,val in ws.get_rows(): #遍历所有行
if not name.value in dic: #判断字典中是否存在key
dic[name.value]=[val.value] #不存在则给key写入值
else:
dic[name.value].append(val.value) #存在则给值增加元素
for m in range(1,13): #循环生成12个月份
m_num=['{:02}月'.format(m)] #调整格式
val_num |=set(m_num) #转换成集合类型
for key,item in dic.items(): #将字典的所有内容带入循环
lst=list(val_num-set(item)) #用生成的12个月份集合差集字典的值元素,并转换为列表类型
lst.sort() #重新排序
nws.write(row_num,0,key) #字典的第一个key是表头“姓名”,所以直接写入
nws.write(row_num, 1, '、'.join(lst))
row_num += 1
nws.write(0,1,'未达标月份') #字典值的第一个是12个月份,所以需要重新写入表头
nwb.save('8-6-3-1.xls')