07.Python字典和集合

配套视频教程

本文B站配套视频教程

一、Set 集合的概念

1. set 集合的性质

set 集合是一组无序的且不能重复的集合,打印 set 集合时会自动消除重复的元素项;
set 集合用大括号表示;
set 集合存储的时候就是无序的,它不支持通过索引的方式进行访问;
set 集合在初始化时的顺序与打印出来时的顺序是不一样的;

set01 = {11,22,33,44,55}

2. set 集合存储的原理

set 集合在存储的时候,先把元素转为哈希值,哈希值是顺序存储的,哈希算法是用来判断两个对象是否是同一个;

3. 创键 set 集合的方法

(1)创建的时候,直接初始化

# 创建set集合
set01 = {11,22,33,44,55,66,77}
print(set01)

(2)创建空的 set 集合,然后往里加入值
创建空 set 不能想当然的使用set{},这样创建的是一个空字典,创建空 set 集合应该使用方法set()

# 创建空set
set02 = set()
set02.add("Tom")
set02.add("Bob")
set02.add("Jerry")
print(set02)

4.遍历 set 集合的方法

使用 for 循环遍历集合

# 遍历set集合
set01 = {11,22,33,44,55,66,77}
for i in set01:
    print(i,end=" ")

二、set 集合常用方法

1. 不可以使用加法运算和乘法运算符

列表可以使用加法运算符将两个列表拼接在一起,set 集合不可以使用;
列表可以使用乘法运算符将指定列表打印指定次数,set 集合不可以使用;

2. 赋值运算符
set01 = {11,22,33}
set02 = set01

3. 返回集合中元素的长度
set01 = {11,22,33}
print(len(set01))

4. 判断是否包含元素
# 判断是否包含元素
set01 = {11,22,33}
print("是否包含22:",22 in set01)

5. 排序和反转

直接的排序是不支持的,sort()reverse()
但是支持临时排序

# set支持临时排序
set01 = {11,2,-1,222,23}
print(sorted(set01))

6. 添加元素

使用 add()方法添加元素

set01 = {11,22,33}
set01.add(44)
print(set01)

7. 删除元素

删除元素有 discard、remove、pop 方法
discard 删除原先不存在的值,集合不发生变化而且也不会报错

# discard方法删除元素
set01 = {11,0,22,-22,99,100,33}
print("删除22前",set01)
set01.discard(22)
print("删除22后",set01)
set01.discard(122)
print("删除一个不存在的122",set01)

输出结果:

删除22前 {0, 33, 99, 100, -22, 11, 22}
删除22后 {0, 33, 99, 100, -22, 11}
删除一个不存在的122 {0, 33, 99, 100, -22, 11}

但是如果用 remove 方法,要删除的值如果不存在,那么程序便会报 KeyError 错;
使用 pop 方法删除,默认删除集合中第一个元素(按照 hash 值存储的),pop 函数的参数不能指定某一个要删除元素的具体的值。

8. 数值元素计算(max,min,sum)
set03 = {11,2,222,12,1,456,-2}
print(min(set03))  # 打印集合中的最小值
print(max(set03))  # 打印集合中的最大值
print(sum(set03))  # 打印集合中的数值元素的和

9. set 集合逻辑运算

交集、并集、差集、对等差集、是否子集、是否父集,两种表示方法任选一个即可;

image

# 逻辑运算
set01 = {11,22,33,44,55}
set02 = {44,55,66,77,88}
# 交集
print(set01 & set02)
print(set01.intersection(set02))
# 并集
print(set01 | set02)
print(set01.union(set02))
# 差集
print(set01 - set02)
print(set01.difference(set02))
# 对等差集
print(set01 ^ set02)
print(set01.symmetric_difference(set02))
print((set01-set02) | (set02-set01))
# 判断是否是子集
set01 = {11,22,33}
set02 = {11,22}
print(set01.issubset(set02))
print(set01 <= set02)
print(set01.issuperset(set02))
print(set01 >= set02)

10. 类型转换

set 集合可以转化为 list 列表、tuple 元组、str 字符串,可以直接通过类型转换来实现:

# 类型转化
set01 = {11,2,2,3,0,1,2}
list01 = list(set01)  # 转换为列表
tuple01 = tuple(set01)  # 转换为元组
str01 = str(set01)  # 转换为字符串

三、set 集合综合案例

案例 01: 生成 0-10 之间 5 个不相等的数

# 生成0-10之间5个不相等的数
import random
set01 = set()
while len(set01) < 5:
    set01.add(random.randint(1,10))
print(set01)

四、字典的概念

1. 概念:

字典是一组无序的且不重复的(key-value)数据集合,它是一种特殊的 set 集合;
字典中元素由 key 和 value 组成,比如:95001:“张三”,
冒号前面称为 key,冒号后面称为 value

2. 注意事项:

(1)通过 key 可以访问 value,反之不可以
(2)对字典某个键值对的值进行访问需要使用字典名加中括号来进行访问

dic01 = {95001:"张三",95002:"李四",95004:"王五"}
print(dic01[95001])

(3)字典中的元素不能重复,即字典中不允许出现相同的键值对,在字典中 key 不能重复,如果多个键值对有相同的 key 则以最后一个 key 的键值对为准,因为覆盖了全面的键值对。
value 是可以重复的;
(4)字典中的键值对是无序的,不可以用下标进行访问
(5)key 必须要是不可改变的类型:int、float、bool、tuple、str,不可以是列表、集合等可以改变的数据类型

# 字典中使用元组作为键表示地理位置经纬度
dic01 = {(32,122):"徐家汇",(31,120):"无锡"}

(6)value 类型可以存储任何类型的 Python 数据类型

五、字典创建和初始化

1. 字典的创建

(1)创建的时候直接初始化

# 字典在创建的时候直接初始化
student_result = {"张三": 342,"李四": 334,"王五": 443}
print(student_result["张三"])

(2)创建空的后期添加

# 创建一个空的字典,后期一个个添加
student_result = {}
student_result["张三"] = 344
student_result["李四"] = 321
student_result["王五"] = 345
print(student_result)

2. 删除字典的元素

删除字典的元素有三种方法
(1)pop()方法
参数传入 key,pop(key)可以删除指定键值对

# 使用pop(key)
student_result = {"张三": 342,"李四": 334,"王五": 443}
print(student_result)
student_result.pop("张三")  # 删除“张三”
print(student_result)

如果传入的 key 不存在,程序会报 keyvalue 异常
(2)popitem()方法
不需要参数即可删除字典中最后一个元素

# 使用popitem() 删除字典的最后一个
student_result = {"张三": 342,"李四": 334,"王五": 443}
print(student_result)
student_result.popitem()
print(student_result)

(3)clear 方法
使用 clear 方法删除整个字典

student_result = {"张三": 342,"李四": 334,"王五": 443}
print(student_result)
student_result.clear()
print(student_result)

六、字典元素的遍历和访问

1. 字典元素的访问

这里我们先假设有一个字典,key 为学生学号,value 为成绩

dict01 = {95001:56,95002:89,95003:77,95004:87}

可以通过 dict01[95001]来访问该学号的,但是如果 key 不存在怎么办呢?有两个解决办法,setdefault()和 get()方法

print(dict01.setdefault(95004,"None")) # 如果key存在正常查找,如果不存在返回定义的"None"
print(dict01.get(95001,"None")) # 避免获取每个key不存在出现异常,所设置的初始值

我们前面关于字典元素的删除也可以通过这种方式来避免异常的发生

print(dict01.pop(95001,"None"))  # 如果key存在则返回对应的值,否则返回None

2. 字典元素的遍历

(1)标准遍历方式

dict01 = {95001:56,95002:89,95003:77,95004:87}
for i in dict01:
    print(i,":",dict01[i])

(2)使用 items 遍历

dict01 = {95001:56,95002:89,95003:77,95004:87}
print(dict01.items())   # 使用items遍历
print(list(dict01.items())) # 结果转化为list
print(list(dict01.items())[0])  # 访问list第一个元素,这里是(95001,56)
# 遍历
list01 = list(dict01.items())
for i in list01:
    print(list(i)[0],list(i)[1])

(3)使用 keys 遍历

keys_list = list(dict01.keys())
for i in keys_list:
    print(i,":",dict01[i])

(4)使用 keys 和 values 遍历

keys_list = list(dict01.keys())  # 把字典转化为keys
values_list = list(dict01.values())  # 把字典转化为values
for i in range(len(keys_list)):
    print(keys_list[i],":",values_list[i])

七、字典的常用方法

1. 合并与多次打印输出

字典和 set 的存储模式使一样的,乘号和加号是不能用的。
两个字典的合并不能用加号,而是用 update 进行合并;
字典的多次打印输出不能像列表那样直接使用乘号

dic01 = {95001:88,95002:99,95003:67}
dic02 = {95004:89,95005:87,95006:99}
# print(dic01 + dic02)  # 加号合并输出不支持
# print(dic01 * 3)  # 乘号多次输出不支持
dic01.update(dic02)
print(dic01)

2. 复制操作

可以直接使用赋值符号将 dic01 赋给 dic03,如果 dic01 里某个元素发生了改变,dic03 也会发生改变。如果不想让 dic03 元素跟着发生改变则可以使用浅复制方法,把存储的每一个值索引复制一份,改变字典元素的一个元素而另外一个复制的字典值不变。

dic03 = dic01.copy()

3. 其它常用操作

(1)获取字典的长度
使用 len()方法获取字典的长度

dic01 = {95001:88,95002:99,95003:67}
print(len(dic01))

(2)判断字典是否包含
使用关键词in判断 key 是否包含

dic01 = {95001:88,95002:99,95003:67}
print(95001 in dic01)

(3)排序
按照 key 进行排序

dic01 = {95001:88,95002:99,95003:67}
print(sorted(dic01))

打印出来的结果为只有 key 的列表
(4)计算
max、min、sum 都是针对 key 的

dic01 = {95001:88,95002:99,95003:67}
print(max(dic01)) # 打印最大的索引
print(min(dic01))  # 打印最小的索引
print(sum(dic01))  # 打印索引的和

(5)用列表作为索引创建新的字典
如果我们已经有了某个列表,我们可以根据列表创建字典的键,比如已知学号列表 student_no,可以创建一个新的由学号列表为键的成绩字典 student_result。

student_no = [95001,95002,95003,95004]  # 学号列表
student_result = {}.fromkeys(student_no)  # 从学号列表获取keys
student_result[95001] = 97  # 对字典中的元素进行直接赋值
print(student_result)

###统计单词出现次数

word="I'm a boby, I'm a girl. When it is true, it is ture. that are cats, the red is red."
word=word.replace(',','').replace('.','')
word=word.split()
print(word)

dict = {}
for key in word:
    dict[key] = dict.get(key, 0) + 1

print(dict)

image.png

已知有十六支男子足球队参加2008 北京奥运会。写一个程序,把这16 支球队随机分为4 个组。采用List集合和随机数

2008 北京奥运会男足参赛国家:

科特迪瓦,阿根廷,澳大利亚,塞尔维亚,荷兰,尼日利亚,日本,美国,中国,新西兰,巴西,比利时,韩国,喀麦隆,洪都拉斯,意大利

提示:分配一个,删除一个

image

import random
groupNum2Countrys = {}

strCountrys = "科特迪瓦,阿根廷,澳大利亚,塞尔维亚,荷兰,尼日利亚,日本,美国,中国,新西兰,巴西,比利时,韩国,喀麦隆,洪都拉斯,意大利";
countryList = strCountrys.split(",")

for i in range(4):
    lstGroup = []
    # // 分第1组
    # // 随机从集合中选出一个国家,放到第1组里;然后将这个选出的国家,从原来集合中干掉(删除)
    # // 重复以上步骤4次
    for j in range(4):
        selectIndex = random.randint(0,len(countryList)-1)
        lstGroup.append(countryList[selectIndex])
        countryList.remove(countryList[selectIndex])

    groupNum2Countrys[i+1] = lstGroup

for key,value in groupNum2Countrys.items():
    print('第' + str(key) + '组')
    print(value)


谁拿了最多的奖学金—Python集合知识综合练习

image.png

问题描述
某校的惯例是在每学期的期末考试之后发放奖学金。发放的奖学金共有五种,获取的条件各自不同:

院士奖学金,每人8000元,期末平均成绩高于80分(>80),并且在本学期内发表1篇或1篇以上论文的学生均可获得;
五四奖学金,每人4000元,期末平均成绩高于85分(>85),并且班级评议成绩高于80分(>80)的学生均可获得;
成绩优秀奖,每人2000元,期末平均成绩高于90分(>90)的学生均可获得;
西部奖学金,每人1000元,期末平均成绩高于85分(>85)的西部省份学生均可获得;
班级贡献奖,每人850元,班级评议成绩高于80分(>80)的学生干部均可获得;
只要符合条件就可以得奖,每项奖学金的获奖人数没有限制,每名学生也可以同时获得多项奖学金。例如姚林的期末平均成绩是87分,班级评议成绩82分,同时他还是一位学生干部,那么他可以同时获得五四奖学金和班级贡献奖,奖金总数是4850元。
基本要求
现在给出若干学生的相关数据,请计算哪些同学获得的奖金总数最高(假设总有同学能满足获得奖学金的条件)。
输入数据格式格式:
输入的第一行是一个整数N(1 <= N <= 100),表示学生的总数。接下来的N行每行是一位学生的数据,从左向右依次是姓名,期末平均成绩,班级评议成绩,是否是学生干部,是否是西部省份学生,以及发表的论文数。姓名是由大小写英文字母组成的长度不超过20的字符串(不含空格);期末平均成绩和班级评议成绩都是0到100之间的整数(包括0和100);是否是学生干部和是否是西部省份学生分别用一个字符表示,Y表示是,N表示不是;发表的论文数是0到10的整数(包括0和10)。每两个相邻数据项之间用一个空格分隔。
输出数据格式:
输出包括三行,第一行是获得最多奖金的学生的姓名,第二行是这名学生获得的奖金总数。如果有两位或两位以上的学生获得的奖金最多,输出他们之中在输入文件中出现最早的学生的姓名。第三行是这N个学生获得的奖学金的总数。
输入
4
YaoLin 87 82 Y N 0
ChenRuiyi 88 78 N Y 1
LiXin 92 88 N N 0
ZhangQin 83 87 Y N 1

输出
ChenRuiyi
9000
28700


# 4
# YaoLin 87 82 Y N 0
# ChenRuiyi 88 78 N Y 1
# LiXin 92 88 N N 0
# ZhangQin 83 87 Y N 1

num = int(input('请输入学生数量:'))
std_dict = {}
for i in range(num):
    line = input(f'请输入第{i+1}名学生信息')
    stu_lst = line.split(' ')
    std_dict[stu_lst[0]] = stu_lst[1:]

# print(std_dict)
reward_dict = {}
#开始计算每一位学生的奖学金
for stu_name,stu_info in std_dict.items():
    if int(stu_info[0]) > 80 and int(stu_info[4]) > 0:
        reward_dict[stu_name] = reward_dict.get(stu_name,0) + 8000
    if int(stu_info[0]) > 85 and int(stu_info[1]) > 80:
        reward_dict[stu_name] = reward_dict.get(stu_name, 0) + 4000
    if int(stu_info[0]) > 90:
        reward_dict[stu_name] = reward_dict.get(stu_name, 0) + 2000
    if int(stu_info[0]) > 85 and stu_info[3] == 'Y':
        reward_dict[stu_name] = reward_dict.get(stu_name, 0) + 1000
    if int(stu_info[1]) > 80 and stu_info[2] == 'Y':
        reward_dict[stu_name] = reward_dict.get(stu_name, 0) + 850

sum = 0
max = 0
max_stu = ''
for stu_name,money in reward_dict.items():
    if max < money:
        max = money
        max_stu = stu_name
    sum += money

print(max_stu)
print(max)
print(sum)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值