- images
- results
- .gitignore
- 1.1概论.ipynb
- 1.2 环境配置.pdf
- 1.3数据类型.ipynb
- 1.4 人机交互.ipynb
- 1.5 对象与变量.ipynb
- 1.6 编码与命名规范.ipynb
- 2.1 数值类型.ipynb
- 2.2 数值类型转换.ipynb
- 2.3 数值元算.ipynb
- 2.4常用数学运算函数.ipynb
- 2.5 math 模块及其应用.ipynb
- 2.6.1 逻辑值测试.ipynb
- 2.6.2 成员运算.ipynb
- 2.6.3 比较运算.ipynb
- 2.6.4 布尔运算.ipynb
- 2.6.5 运算优先级.ipynb
- 2.ipynb
- 3.1 流程控制结构.ipynb
- 3.3.1 for 循环语句.ipynb
- 3.3.3 rang.ipynb
- 3.3.3 while 循环语句.ipynb
- 3.4 and 3.5 分支结构和条件.ipynb
- 3.6 and 3.7 .ipynb
- 3.9 异常处理.ipynb
- 4 函数和模块化编程.ipynb
- 4.1 函数的定义、调用与返回值.ipynb
- 4.2 函数的参数传递.ipynb
- 4.3 变量的作用域.ipynb
- 4.4 匿名函数.ipynb
- 4.5 递归.ipynb
- 4.6 内置函数.ipynb
- 4.7 模块化程序设计.ipynb
- 5.1 序列通用操作.ipynb
- 5.1.1 索引.ipynb
- 5.1.2 切片.ipynb
- 5.1.3 序列拼接与重复.ipynb
- 5.1.4 成员测试.ipynb
- 5.2.1 字符串的创建.ipynb
- 5.2.2 字符串常量.ipynb
- 5.2.4 字符串的遍历.ipynb
- 5.2.5 文件遍历.ipynb
- 5.2.6 字符串的处理方法.ipynb
- 5.2.7 字符串格式化.ipynb
- 5.2.8 转义字符.ipynb
- 5.3 random 模块及其应用.ipynb
- 6.1 元组.ipynb
- 6.2 列表.ipynb
- 6.2.1 列表的创建.ipynb
- 6.2.2 列表的更新.ipynb
- 6.2.3 列表的删除.ipynb
- 6.2.4 列表的排序.ipynb
- 6.2.5 列表赋值与复制.ipynb
- 6.2.6 列表推导式.ipynb
- 6.2.8 常用内置函数.ipynb
- 6.2.9 列表嵌套及其排序.ipynb
- 6.3 列表综合应用.ipynb
- 7.1.1 集合的创建.ipynb
- 7.1.2可变集合类型的操作.ipynb
- 7.1.3 成员关系.ipynb
- 7.1.4 集合关系.ipynb
- 7.1.5 集合运算.ipynb
- 7.2.1 字典创建.ipynb
- 7.2.2 获取字典值.ipynb
- 7.2.3 修改字典值.ipynb
- 7.2.4内置函数与方法.ipynb
- 7.2.5字典排序输出.ipynb
- 7.3 集合与字典的应用.ipynb
- 8 中 numpy 概述.ipynb
- 8 中panda 库.ipynb
- 8.1 文件的打开与关闭.ipynb
- 8.2 文件读写操作.ipynb
- 8.3 文件的应用.ipynb
- 8.4 numpy 文件操作.ipynb
- 8.4.2 and 3.ipynb
- 8.5.1 pandas文件读写.ipynb
- 8.5.2 and 3 and 4.ipynb
- 9.1 matplotlib 线性图.ipynb
- 9.1.5 数据文化绘图.ipynb
- 9.2 非线性图.ipynb
- 9.3 词云.ipynb
- _overview.md
- _readme.ipynb
- coding_here.ipynb
- dream.png
- score.txt
- score_total.csv
- 成绩分析综合.json
7.1.1 集合的创建.ipynb @master — view markup · raw · history · blame
集合(set)¶
集合类型用来保存**无序**的、**不重复**的不可变数据</font>,其概念和数学中集合的概念基本一致,如果我们把一定范围的、确定的、可以区别的事物当作一个整体来看待,那么这个整体就是集合,集合中的各个事物称为集合的元素。通常,集合需要满足以下特性:
1.无序性:一个集合中,每个元素的地位都是相同的,元素之间是无序的。 2.互异性:一个集合中,任何两个元素都是不相同的,即元素在集合中只能出现一次,集合中不存在重复的元素。 3.确定性:给定一个集合和一个任意元素,该元素要么属这个集合,要么不属于这个集合,二者必居其一,不允许有模棱两可的情况出现。
set1 = {'Python', 'C++', 'Java', 'Kotlin', 'Swift'} # 集合
for elem in set1: # 遍历集合中的元素
print(elem,end=' ')
# 每次运行结果可能不同
# C++ Swift Python Kotlin Java
# Java Kotlin C++ Swift Python
无序性说明集合中的元素并不像列中的元素那样存在某种次序,可以通过索引运算就能访问任意元素,集合并不支持索引运算。
集合的互异性决定了集合中不能有重复元素,这一点也是集合区别于列表的地方,我们无法将重复的元素添加到一个集合中。集合类型必然是支持in和not in成员运算的,这样就可以确定一个元素是否属于集合,也就是上面所说的集合的确定性。
集合的成员运算在性能上要优于列表的成员运算,这是集合的底层存储特性决定的(集合底层使用了哈希存储(散列存储))
可近似将集合看成是没有值的字典。
常见的用途:
1.成员检测
2.从序列中去除重复项
3.数学中的集合类计算
目前有两种内置集合类型:
**集合(set)**
**不可变集合(frozenset)**
set和frozenset的关系类似于列表和元组的关系。
set 类型是可变但 unhashable的,其内容可以使用 add() 和 remove() 这样的方法来改变, 但不能被用作字典的键或其他集合的元素;
frozenset 类型是不可变并且为 hashable,因此它可以被用作字典的键或其他集合的元素。
1. 集合的创建¶
1.1 非空集合可通过将一系列用逗号分隔的数据放在一对**大括号**中的方法创建。¶
setA = {1, 2, 3, 4, 5} # 将集合数据赋值给变量,直接创建集合
print(setA) # 输出集合{1, 2, 3, 4, 5}
setB = {'吉林', '武汉', '北京'}
print(setB) # {'北京', '吉林', '武汉'}
setC = {(1, 2, 3,3), 1, 2, 3.14, 'hello',(1, 2, 3,3)}
print(setC) # {(1, 2, 3), 1, 2, 3.14, 'hello'}

需要注意的是,。{}中需要至少有一个元素,不能直接使用**“{}”**来创建和表示**空集合**,“{}”将创建一个**空字典**
setD = {1} # 将创建一个空字典
print(setD)
print(type(setD)) # 输出类型为dict
集合元素必须为不可变类型**</font>,如“{}”内包含可变类型,将会抛TypeError异常。
setC = {[1, 2, 3], 1, 2, 3.14, 'hello'} # 列表[1,2,3]为可变类型,抛TypeError异常
由于集合元素**不重复**,如包含重复元素,将会**去重**。
set_1 = {(1, 2, 3), 1, 1, 1, 1, 1, 2, 3.14, 'hello'} # 包含多个整数1,将会去重,最终字典中将只包含一个1
print(set_1) # {1, 2, 3.14, 'hello', (1, 2, 3)}
set_2 = {0, 0.0 ,0j} # 由于数值上 0 == 0.0 == 0j,所以同样会去重
print(set_2) # {0}

1.2 使用 set() 函数可创建集合(set)¶
set()和 frozenset()函数又称为集合构造器,分别用来生成可变和不可变的集合。
如果提供一个参数,则该**参数**必须是可迭代的,即参数必须是序列、列表、元组、推导式、迭代器或字典等支持**迭代的**对象。
setE = set(range(8)) # 通过range创建集合 {0, 1, 2, 3, 4, 5, 6, 7}并赋值给 S5
print(setE) # 输出{0, 1, 2, 3, 4, 5, 6, 7}
setF = set([1, 2, 3, 4, 5]) # set()将列表转为集合 {1, 2, 3, 4, 5}
print(setF) # 输出{1, 2, 3, 4, 5}
print(set('cheeseshop')) # 字符串转为集合,去掉重复元素, {'c', 'p', 'o', 'e', 's', 'h'}
1.3 使用 frozenset() 函数可创建不可变集合(frozenset)¶
setG = frozenset((1, 3, 5, 7)) # 用frozenset()函数将元组转为不可变集合
print(setG) # 输出 frozenset({1, 3, 5, 7})
如果不提供任何参数,默认会生成**空集合**。
setI = set() # 使用函数创建一个空集合,空集合不能使用{}创建和表示
print(setI) # 输出 set()
setJ = frozenset() # 使用 frozenset()函数构造器创建一个空的不可变集合
print(setJ) # 输出 frozenset()
1.4 利用集合推导式¶
与列表推导式类似,集合也可以通过集合推导式创建。
集合推导式与列表推导式的唯一区别在于用**{}**代替[]。
setH = {i*i for i in range(5)} # 利用推导式生成集合
print(setH) # {0, 1, 4, 9, 16}
集合中的元素必须是hashable类型,使用哈希存储的容器都会对元素提出这一要求。
所谓hashable类型指的是能够计算出哈希码的数据类型,通常不可变类型都是hashable类型,如:
整数(int)、浮点小数(float)、布尔值(bool)、字符串(str)、元组(tuple)等。
可变类型都不是hashable类型,因为可变类型无法计算出确定的哈希码,所以它们不能放到集合中。例如:我们不能将列表作为集合中的元素;同理,由于集合本身也是可变类型,所以集合也不能作为集合中的元素。
我们可以创建出嵌套的列表,但是我们不能创建出嵌套的集合,这一点在使用集合的时候一定要引起注意。
1.5 集合变量也可以赋值给另一个变量¶
但这时,两个变量指向相同的内存,当一个集合元素发生变化时,另一个集合的元素同时也会**发生变化**。
如果需要创建的一个原集合内容一致的**不同集合对象**时,可以使用**s.copy()**的方法。
city_set = {'吉林', '武汉', '北京'}
new_city_set = city_set # 将集合变量city_set赋值给new_city_set,此时两个变量指向相同的内存
city_set.add('深圳') # 为集合city_set添加一个元素'深圳',new_city_set也会同时变化
print(city_set)
print(new_city_set)
如果需要创建的一个原集合内容一致的不同集合对象时,可以使用s.copy()的方法。
city_set = {'吉林', '武汉', '北京'}
new_city_set = city_set.copy() # 创建的一个集合变量city_set内容一致的新集合对象new_city_set
city_set.add('深圳') # 为集合city_set添加一个元素'深圳',不影响new_city_set
print(city_set)
print(new_city_set)
2. 集合去重特性的应用¶
由于集合(set)内的数据是**不重复**的,因此集合构造器常用来对其他的序列数据进行**“去重操作”**。
setA = set((90, 75, 88, 65, 90))
print(setA) # 输出{88, 65, 90, 75},重复的90被去掉
scores = [80, 85, 88, 93, 88, 81, 96, 73, 85, 77, 77, 86, 89, 68, 93, 82, 95, 81, 80, 70]
# 输出不重复的4个最低分 [68, 70, 73, 77]
# 用set()函数将score转为集合,同时去除重复的数字,list()函数再将集合转为列表
# 用sorted()函数对集合元素进行升序排序,再切片取排序后列表的前4个数
print(sorted(set(scores))[0:4])

集合支持Python内置函数 len(s),用于获取集合s中数据元素的个数。
可根据序列对象转换为集合后前后**长度的变化**判定其中是否存在**重复元素**。
实例7.1: 奇特的四位数¶
一个四位数,各位数字互不相同,所有数字之和等于6,并且这个数是11的倍数。满足这种要求的四位数有多少个?各是什么?
分析:
将这个四位数转为集合,如果各位上有相同数字存在,重复数字会被去掉,则生成的集合长度len(set(str(i)))必小于4,只有长度等于4的集合,其对应的数中才无重复数字。
所有数字之和等于6,并不需要从0000遍历到9999,只需要遍历到3210即可。
若这个数是11的倍数,则该数对11取模的值应该等于0。
其中map(int,list(str(i)))是将数字i 转为字符,再转为列表,map(int,ls)函数的作用是将序列ls中的每个元素映射为第一个参数指定的数据类型,此处是映射为整型。
# 输出各位数字互不相同、所有数字之和等于6,且是11的倍数的4位数
ls = []
for i in range(1000,3211): # 各位数加和为6的最大的无重复数字的数是3210
if i % 11 == 0 and sum(map(int,str(i))) == 6 and len(set(str(i))) == 4:
ls.append(i) # 符合条件的数字加到列表ls里
print(len(ls)) # 列表长度就是符合条件的数字的个数 6
print(ls) # [1023, 1320, 2013, 2310, 3102, 3201]
实例7.2: 特殊的生日¶
每个日期可以转成8位数字,比如2018年5月12日 对应的就是 20180512。小明发现,自己的生日转成8位数字后,8个数字都没有重复,而且自他出生之后到今天,再也没有这样的日期了。请问小明的生日是哪天?
分析:
可以从当前日期开始向前逐日判定是否为满足条件的日期,为提高效率,可以略过一些不能表示合法日期的数字,例如月份位超过12的和日期位超过31的数字,同时确保最后得到的数字是合法日期。
# 从当前日期向前查找第一个没有重复数字的日期
day = 20200202 # 当前日期,整型
while True:
day = day - 1 # 从当前日期向前逐日判定
strDay = str(day) # 整型转字符串
if int(strDay[4:6])>13:
continue # 忽略月份超过12的数字
elif strDay[4:6] in ['01','03','05','07','08','10','12'] and int(strDay[-2:]) > 31:
continue # 以上月份,忽略超过31的日期
elif strDay[4:6] in ['04','06','09','11'] and int(strDay[-2:]) > 30:
continue # 以上月份,忽略超过30的日期
elif strDay[4:6] in ['02'] and int(strDay[-2:]) > 19:
continue # 2月份,忽略超过19的日期,20以后有重复数字
elif len(set(strDay)) == 8: # 字符串转集合,判断无重复数字是否8个
print(strDay)
break # 找到第一个满足条件的日期中止循环 19870625
上面的代码使用了大量的分支结构,用于排除不合法的日期,程序较复杂。
这个问题也可以借助datetime库里的一些方法实现:
获取今天日期的方法是datetime.now(),可得到形如2018-09-04的日期。
返回日期间隔的方法是timedelta(days=1),括号中的days=1表示日期间隔为1天。
从当前天向前查看每一天的日期中是否有重复数字,第一个出现的没有重复数字的日期就是答案。
判断日期中是否有重复数字可用集合方法。
使用datetime库简化后的代码如下:
# 从当前日期向前查找第一个没有重复数字的日期
import datetime
todays = datetime.datetime.now() # 获取今天日期形如:2020-02-02
while True:
todays = todays -datetime.timedelta(days=1) # 从今天起日期依次减一天
sday = todays.strftime('%Y%m%d') # 获得格式化的时间,形如:20190701
if len(set(sday)) == 8: # 字符串转集合,判断无重复数字是否8个
print('出生日期是{}年{}月{}日'.format(sday[:4],sday[4:6],sday[6:]))
break # 找到一个符合条件的日期就结束循环
datetime是一个非常有用的内置库,几乎和日期或时间相关的操作都可以找到相关的函数或方法,遇到相关的需求可查阅datetime库官方文档获取帮助。
练一练
猜年龄¶
美国数学家维纳(N.Wiener)智力早熟,11岁就上了大学。他曾在1935~1936年应邀来中国清华大学讲学。一次,他参加某个重要会议,年轻的脸孔引人注目。于是有人询问他的年龄,他回答说:“我年龄的立方是个4位数。我年龄的4次方是个6位数。这10个数字正好包含了从0到9这10个数字,每个都恰好出现1次。” 请编程输出当年维纳的年龄。
本题没有输入,输出应为18(维纳当年的年龄)
提示:循环遍历所有可能的年龄,将年龄值的立方和4次方的结果转换为字符串并拼接起来,若该字符串转化为集合后长度长度仍为10,则是正确的年龄。
# 请在此处编写代码,完成上面的题目的要求