组合数据类型
集合类型及操作符
集合类型定义
集合:多个元素的无序组合,不存在顺序区分。同数学中的定义一样。
集合类型:集合中每一个数据都是独一无二的,因此要求组成它的元素是不可变的类型,例如整数、浮点数、元组。
集合也可以用set()定义,注意空集只能用set()定义,不能用{}定义,因为这是字典类型的默认定义,同时set("str")会把字符串拆开成为一个个分别的字符。
a = {"a","b","c",(1,2), a}
a = set("pyp")
>>> {'p','y'}
a = {1, 2, 1, 2}
>>>{1,2}
注意:
- 集合用大括号{}表示,元素间用逗号分割
- 集合不包含不同元素
- 集合内的元素之间没有顺序之分。
集合之间的运算
基本操作符:交叉并补包含等基本运算。结果返回一个新值,但不改变原值。
操作符 | 功能 |
a|b | 表示a与b的并集 |
a - b | 表示a与b的差集 |
a&b | 表示a与b的交集 |
a^b | 表示a与b的非交集的 |
a<=b | 表示a是否包含于b的包含关系 |
a>=b | 表示a是否包含b的判断 |
增强操作符:会改变原本集合的元素。 | |
操作符 | 含义 |
:-----: | :---------------------: |
S &= T | 更新S为原本S与T的交集 |
S |=T | 更新S为原本S与T的并集 |
S -=T | 更新S为原本S与T的差集 |
S ^=T | 更新S为原本S与T的非差集 |
a = {'a','b',1}
b = set("ab1")
a&b
>>>{'a','b'}
a|b
>>>{'a','b','1', 1}
a^b
>>>{'1',1}
a-b
>>>{1}
集合的处理方法
操作函数或方法 | 功能 |
S.add(x) | 向集合中加入一个元素x |
S.discard(x) | 丢弃一个集合中元素x,若不存在,不报错 |
S.remove(x) | 丢弃一个集合中元素x,若补存在,产生keyerror异常 |
S.clear() | 清空集合中的元素 |
S.pop() | 随机取出(返回并删除)集合中一个元素,若集合为空产生keyerror异常 |
S.copy() | 返回一个集合的副本 |
len(S) | 返回集合元素的个数 |
x in S | 判断x是否在S中 |
x not in S | 判断x是否不在S中 |
set(X) | 将其他类型的变量x转换为集合类型 |
a = {'a', 'b','c'}
for i in a:
print(i)
>>>c,a,b #顺序与定义的顺序无关
try:
while True:
print(a.pop(), end="") #利用异常结束循环完成遍历
except:
pass
集合的应用
- 去判断数据的包含关系
- 数据去重
li = {'a','a','b','b',1}
s = set(li)
li_1 = list(s)
#li_1 = ['a','a',1]
序列类型及操作
序列类型的定义
序列:元素之间存在先后关系,类似于一维向量。因而可以又重复的元素。序列是一种基类类型,字符串,元组都是它的衍生。
序号:序列类型的序号即字符串的索引。
序列处理函数与方法
处理函数 | 描述 |
x in S | 判断元素x是否在S中 |
x not in S | 判断元素x是否不在S中 |
a * S | 返回S重复a次 |
s + t | 返回s与t序列的合并 |
s[i] | 返回s序列中第j+1个元素 |
s[i: j :k] | 从序列中S[i]到S[j]以k为步长遍历 |
len(S) | 返回S的元素个数 |
min(S) | 返回S中最小元素,需要元素可比否则报错 |
max(S) | 返回S中最大元素,需要元素可比否则报错 |
S.index(x[, i, j]) | 返回从i到j之间第一个x出现的位置 |
S.count(x) | 返回序列中x出现的个数 |
元组类型与操作
元组是一种序列类型,一旦创建就不能修改。
使用tuple()定义,或者用()直接定义。
元组类型不能改变所以没有什么特殊操作,继承了基本全部的序列操作。
creature = ("cat", "dog", "bat", "duck")
creature[::-1]
>>>("duck", "bat", "dog", "cat") #生成了一个新的元组而非改变原本元组
列表类型与操作
- 列表也是一种序列类型,但是允许修改。
注意:列表类型在定义时,如果使用了[]或者list()函数,那么真正创建了一个列表,反之,如果只是用list1 = list2,那么只是相当于重新命名,对list2作改变会直接影响到list1的值。 - 列表的操作方法
处理函数 | 描述 |
ls[i] = x | 把ls第i位置元素赋值为x |
ls[i:j:k] = x | 把ls从i起到j为止步长为k赋值为x |
del ls[i] | 删除ls第i位置的元素 |
del ls[i:j:k] | 删除ls中自i开始到j为止步长为k的范围的元素 |
ls += lt | 把ls与lt合并 |
ls *=n | 把ls重复n次赋值给自己 |
ls.append(x) | 在ls后面加上一个元素x |
ls.clear() | 清空ls |
ls.cpoy() | 返回一个ls的复制 |
ls.insert(i, x) | 在ls第i位置插入元素x |
ls.pop(i) | 取出la中dii位置的元素 |
ls.remove(x) | 删除ls中第一个元素x |
ls.reverse() | 把列表ls反转 |
实例Ⅸ:基本统计值计算
通过len()就可以得到其元素个数,也可以通过for...in遍历,中位数则通过排序得到。
def getNum():
nums = []
inputnums = input("请输入数字(回车退出):")
while inputnums!="":
nums.append(eval(inputnums))
inputnums = input("请输入数字(回车退出):")
return nums
def mean(nums):
s = 0.0
for i in nums:
s += i
return s/len(nums)
def dev(nums, mean):
s = 0.0
for i in nums:
s += (i-mean)**2
return pow(s/(len(nums)-1), 0.5)
def median(nums):
sorted(nums)
if len(nums)%2==0:
return (nums[len(nums)//2-1]+nums[len(nums)//2])/2
else:
return nums[len(nums)//2]
n = getNum()
m = mean(n)
print("平均值:{:},方差:{:.2},中位数:{}".format(m, dev(n, m), median(n)))
学会多个输入。
采用模块化方法将复杂功能分割为小的模块。
字典类型及操作
字典类型定义
映射:是一种索引(键)和值(数据)的对应。
实际上映射无处不在。
字典类型就是映射的体现,字典是键值对的集合,键值对之间无序。
采用{<键值>:<数据>}或则dict()来定义。
d = {"中国":"北京","美国":"华盛顿","法国":"巴黎"}
d["中国"]
>>>"北京"
字典类型的处理函数加方法
操作符 | 描述 |
del d[k] | 删除d中键值为k的键值对 |
k in d | 判断键值k是否在d中 |
d.keys() | 返回d的全部键值 |
d.values() | 返回d的全部数据 |
d.items() | 返回d的全部键值对 |
d.get(k[,default]) | 返回一个键值为k的数据,找不到返回default |
d.pop(k[, default]) | 取出一个键值为k的数据,找不到返回default |
d.popitem() | 随机取出一个键值对 |
d.clear() | 清空字典 |
len(d) | 返回字典键值对的个数 |
以下是若干示例 |
d = {"中国":"北京","美国":"华盛顿","法国":"巴黎"}
"中国" in d
>>>True
d.keys()
>>>dict_keys(['中国', '美国', '法国'])
d.values()
>>>dict_values(['北京', '华盛顿', '巴黎'])
# 注意:这里的结果虽然也可以用in来遍历,但不是列表值!!!
d.get("中国","伊斯兰堡")
>>>'北京'
d.get("巴基斯坦","伊斯兰堡")
>>>'伊斯兰堡'
字典类型的应用场景
字典最主要作用:表示映射
例如:统计数据出现的次数,键值为数据,数值为出现次数
模块5:jieba库的介绍
jieba库的基本介绍
jieba是优秀的中文分词第三方库。
利用一个中文词库来区分中文词组
jieba库的基本使用
精确模式,全模式,搜索引擎模式
- 精确模式:把一段中文文本精确地分割成各个单词,不含冗余字符
- 全模式:把一段中文文本尽可能地划分为各个单词,相互之间可能有字符重复
- 搜索引擎模式:先用精确模式划分,针对精确划分得到的较长的词汇再做全模式划分
操作函数 | 功能 |
jieba.lcut(s) | 精确模式,返回一个精确地分词结果 |
jieba.lcut(s, cut_all = True) | 全模式,返回全部词汇结果,含有冗余字符 |
jieba.lcut_for_search(s) | 搜索引擎模式 |
jieba.add_word(w) | 向词库添加新词 |
以下是一些例子 |
s = "中国是一个伟大的国家"
jieba.lcut(s)
>>>['中国', '是', '一个', '伟大', '的', '国家']
jieba.lcut(s, cut_all = True)
>>>['中国', '国是', '一个', '伟大', '的', '国家']
s = "中华人民共和国是伟大的"
jieba.lcut_for_search(s)
>>>['中华', '华人', '人民', '共和', '共和国', '中华人民共和国', '是', '伟大', '的']
实例10:文本词频统计
问题分析
基本需求:分析文章中的词汇出现频率。
这对语言有所要求。
以英文戏剧《哈姆雷特》分析词频和中国小说《三国演义》分析人物出场次数为例。
哈姆雷特英文词频统计实例
使用了open操作将在下一章介绍。
def getText():
txt = open("hamlet.txt","r").read()
txt = txt.lower()
for ch in txt:
if ch in '!"#$%&()*+,-./:;<=>?@[\\]^_‘{|}~':
txt = txt.replace(ch, " ")
return txt
hamletTxt = getText()
words = hamletTxt.split()
counts = {}
for word in words:
counts[word] = counts.get(word, 0) + 1
items = list(counts.items())
#这里应该是把字典每一个键值对输出为元组列表的元素
items.sort(key= lambda x:x[1], reverse=True)
#关于这一句,
for i in range(10):
word, count = items[i]
print("{0:<10}{1:>5}".format(word, count))
三国演义人物出场次数
使用jieba库使得中文的标点符号自动被去除了。
因而不用进行上面哈姆雷特文本切割做的标点转换工作。
import jieba
excludes = {"将军","却说","荆州","二人","不可","不能","如此","商议","如何",\
"主公", "军士","左右","军马","引兵","次日","大喜","天下","东吴","于是","今日",\
"不敢","魏兵","陛下","一人","都督","人马","不知"}
txt = open("threekingdoms.txt","r",encoding="utf-8").read()
words = jieba.lcut(txt)
counts={}
for word in words:
if len(word)==1:
continue
elif word=="孔明曰" or word=="诸葛亮":
rword = "孔明"
elif word=="关公" or word=="云长":
rword = "关羽"
elif word=="玄德" or word=="玄德曰":
rword = "刘备"
elif word == "孟德" or word=="丞相":
rword = "曹操"
else:
rword = word
counts[rword] = counts.get(rword, 0) + 1
for word in excludes:
del counts[word]
items = list(counts.items())
items.sort(key= lambda x:x[1], reverse = True)
for i in range(10):
word, count = items[i]
print("{0:<10}{1:>5}".format(word, count))
这里要稍微吐槽一下嵩天老师的结论:因为丞相里很多应该是诸葛亮,所以绝对是诸葛亮第一的。然后曹操也没统计阿瞒、曹贼等等称呼,包括诸葛亮的诸葛村夫啊、刘备的大耳贼啊、孙权的碧眼小儿紫髯鼠辈(孙权一个词就出现了两次,哈哈)啊等等所以结果还是差很多的,包括出现频率很多的都督其实也是很多人(孙吴四都督,还有司马懿都用过)共用的,还有陛下这类多人共用的词汇等等,嵩天老师还有个前二十的人名,真是不知道排除了多少个词了哈哈哈。
课后习题
- 人名独特性统计
s = '''双儿 洪七公 赵敏 赵敏 逍遥子 鳌拜 殷天正 金轮法王 乔峰 杨过 洪七公 郭靖
杨逍 鳌拜 殷天正 段誉 杨逍 慕容复 阿紫 慕容复 郭芙 乔峰 令狐冲 郭芙
金轮法王 小龙女 杨过 慕容复 梅超风 李莫愁 洪七公 张无忌 梅超风 杨逍
鳌拜 岳不群 黄药师 黄蓉 段誉 金轮法王 忽必烈 忽必烈 张三丰 乔峰 乔峰
阿紫 乔峰 金轮法王 袁冠南 张无忌 郭襄 黄蓉 李莫愁 赵敏 赵敏 郭芙 张三丰
乔峰 赵敏 梅超风 双儿 鳌拜 陈家洛 袁冠南 郭芙 郭芙 杨逍 赵敏 金轮法王
忽必烈 慕容复 张三丰 杨逍 令狐冲 黄药师 袁冠南 杨逍 完颜洪烈 殷天正
李莫愁 阿紫 逍遥子 乔峰 逍遥子 完颜洪烈 郭芙 杨逍 张无忌 杨过 慕容复
逍遥子 虚竹 双儿 乔峰 郭芙 黄蓉 李莫愁 陈家洛 杨过 忽必烈 鳌拜 王语嫣
洪七公 韦小宝 阿朱 梅超风 段誉 岳灵珊 完颜洪烈 乔峰 段誉 杨过 杨过 慕容复
黄蓉 杨过 阿紫 杨逍 张三丰 张三丰 赵敏 张三丰 杨逍 黄蓉 金轮法王 郭襄
张三丰 令狐冲 郭芙 韦小宝 黄药师 阿紫 韦小宝 金轮法王 杨逍 令狐冲 阿紫
洪七公 袁冠南 双儿 郭靖 鳌拜 谢逊 阿紫 郭襄 梅超风 张无忌 段誉 忽必烈
完颜洪烈 双儿 逍遥子 谢逊 完颜洪烈 殷天正 金轮法王 张三丰 双儿 郭襄 阿朱
郭襄 双儿 李莫愁 郭襄 忽必烈 金轮法王 张无忌 鳌拜 忽必烈 郭襄 令狐冲
谢逊 梅超风 殷天正 段誉 袁冠南 张三丰 王语嫣 阿紫 谢逊 杨过 郭靖 黄蓉
双儿 灭绝师太 段誉 张无忌 陈家洛 黄蓉 鳌拜 黄药师 逍遥子 忽必烈 赵敏
逍遥子 完颜洪烈 金轮法王 双儿 鳌拜 洪七公 郭芙 郭襄'''
s = s.split()
print(len(set(s)))
- 字典翻转输出
try:
d = eval(input())
d1 = {}
for items in d.items():
d1[items[1]] = items[0]
print(d1)
except:
print("输入错误")
- 《沉默的羔羊》之最多单词
import jieba
txt = open("沉默的羔羊.txt","r",encoding
= "utf-8").read()
txt = jieba.lcut(txt)
d = {}
for word in txt:
if len(word)==1:
continue
else:
d[word] = d.get(word, 0)+1
items = list(d.items())
items.sort(key= lambda x:x[1], reverse=True)
print(items[0][0])
没做Unicode的排序,因为不会。而且这里一个词都有多个字,如果排序那么应该是要取出首字然后decode针对频次相同的进行比较。我想大概是这么个思路。