W7 元组、集合和字典
- 执行命令
a=set((8,7))
后,变量a的内容为集合{8,7}
- 元组一旦创建就不能被修改
- 一个元组可以作为另一个元组的元素,可以采用多级索引获取信息
- Python 中元组采用逗号和圆括号(可选)来表示
- 元组的处理速度比列表快。
- 创建字典:注意最后一种要用标识符
fac={'math': '0001', 'python': '0002', 'c': '0003'} fac=dict([("math","0001"),("python","0002"),("c","0003")]) fac=dict(math="0001",python="0002",c="0003")
- 不可变对象可作为字典的键,如数字、字符串、元组
- 可变对象不可以作为字典的键,如:列表、字典等
- 字典方法
方法 | 功效 |
keys() | 返回由全部的键组成的一个迭代器 |
values() | 返回由全部的值组成的一个迭代器 |
items() | 返回一个迭代器,其中的每一项是一个元组,每个元组由键和它对应的值组成 |
clear() | 删除所有条目 |
get(key,value) | 返回这个键所对应的值,如找不到返回 value |
pop(key) | 返回这个键所对应的值,同时删除这个条目 |
字典遍历
#方法一 score = {'张三':78, '李四':92, '王五':89} for name in score: print(f'{name}:{score[name]}') #方法二 score = {'张三':78, '李四':92, '王五':89} for key,value in score.items(): print(f'{key}:{value}')
判断空表
t = [] print(t==[]) print(len(t)==0) #非常不建议第二种方法 print(not t)
- 以下代码为什么错了:
if c='C' or 'c':
因为
'c'
是True
。四则运算
result={ "+":"x+y", "-":"x-y", "*":"x*y", "/":'x/y if y!=0 else "divided by zero"'} x=int(input()) z=input().strip() y=int(input()) r=eval(result.get(z)) if type(r)!=str: print(format(r,'.2f')) else: print(r)
输⼊⼀⾏字符,求每个字符出现的次数
- 建字典
countchar
,键是字符,值是字符出现的次数。由于不能预知出现哪些字符,所以不能预先初始化字典
- 注意字典的get函数:
get()
函数返回指定键的值,如果值不在字典中返回默认值。countchar.get(c,0)
函数返回键为c的值, 不在字典中返回0。
str=input() countchar={} for c in str: countchar[c]=countchar.get(c,0)+1 print(countchar)
生成素数表
方法一
n=int(input()) prime=[] for x in range(2,n): for k in prime: if x%k==0: break else: prime.append(x) print(*prime, sep=',')
方法二:塞法
n=int(input()) prime = list(range(2,n)) for x in prime: for k in range(x*2, n, x): if k in prime: prime.remove(k) print(prime)
利用了列表的可变性,如果使用
range()
就做不到,因为range()
是不可变的。- 对于
prime
中的每一个x
,删掉它的所有的倍数
- 由于的小于的倍数已经在之前出现过了,所以从开始
- 加
if k in prime
是因为存在2的倍数也是3的倍数的情况
for x in prime
每一轮取下一个元素的时候,是在当时的prime
列表上取,所以也是动态的,删掉了的数不会再出现
多项式求值
- 给定多项式,如,给出不同的值,计算
- 给出多项式的项数(次数)和每项(次)的系数,及值,求多项式的值
5 3 2 3 -2 (依次表示的值为5,3次多项式,2、1、0次的系数)
比较慢的算法:
x = float(input()) n = int(input()) coefficients = map(float, input().split()) f = 0 i = n-1 for a in coefficients: f += a*x**i i -= 1 print(f)
如何加速?
把一个n次多项式
改写成如下形式:
- 令结果
y=0
- 从最高次开始遍历所有的系数a
y += y*x+a
- 这样,求n次多项式f(x)的值就转化为求n个一次多项式的值。
算法示例:
x = float(input()) n = int(input()) coefficients = map(float, input().split()) f = 0 for a in coefficients: f = f*x+a print(f)
元组
- 元组一旦制造出来,就不能修改
- 不能修改元组的内容,也不能修改元组的元素的值
- 元组就是不可修改的列表
- 单个元素的元组用
a = (10,)
表示
enumerate()
函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在for
循环当中。
- 使⽤
set()
创建⼀个空集合
- Python的集合(set)是⼀类容器,元素没有先后顺序,并且元素的值不重复。集合的字⾯量⽤花括号{}
- 集合的元素是不可变对象
- 但是集合本身是可变的
- 下表给出了集合的操作和访问函数。表中示例中的s的值为{2,3,5,7,11}
函数 | 示例 | 结果 | 说明 |
len() | len(s) | 5 | 返回集合中元素的数量 |
min() | min(s) | 2 | 返回集合中最⼩的元素 |
max() | max(s) | 11 | 返回集合中最⼤的元素 |
sum() | sum(s) | 27 | 将集合中所有的元素累加起来 |
add() | s.add(13) | {2,3,5,7,11,13} | 将⼀个元素加⼊集合中 |
remove() | s.remove(3) | {2,5,7,11} | 从集合中删除⼀个元素,如果这个元素在集合中不存在,则抛出KeyError异常 |
- 假设2个集合:
s1 = {2,3,5,7,11};s2 = {2,3,4,5,6,7}
,下表给出4种集合运算的示例
运算 | 函数 | 运算符 | 示例 | 结果 | 说明 |
并集 | union() | | | s1.union(s2) | {2,3,4,5,6,7,11} | 结果是包含两个集合中所有元素的新集合 |
交集 | intersection() | & | s1 & s2 | {2,3,5,7} | 交集是只包含两个集合中都有的元素的新集合 |
差集 | difference() | - | s1 - s2 | {11} | s1-s2的结果是出现在s1 但不出现在s2的元素的新集合 |
对称差 | symmertric_difference() | ^ | s1 ^ s2 | {4,6,11} | 结果是⼀个除了共同元素之外的所有元素 |
实验
猴子选大王
一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。请问是原来第几号猴子当选猴王?
n = int(input()) lst = list(range(1,n+1)) i=-1 while len(lst)>1: i += 3 i %= len(lst) del lst[i] i -= 1 print(lst[0])
删除列表中的重复值(使用lst1.sort(key=lst2.index)
)
mailto = ['cc', 'bbbb', 'afa', 'sss', 'bbbb', 'cc', 'shafa'] addr_to.sort(key = mailto.index) print(addr_to)
使用列表实现筛选法求素数
n=int(input()) prime=list(range(2,n)) for x in prime: for k in range(x*2,n,x): if k in prime: prime.remove(k) print(prime)
输出字母在字符串中位置索引
s=input() t1,t2=input().split() n1,n2=0,0 for index,t in enumerate(reversed(s)): if t==t1 or t==t2: print(f'{len(s)-1-index} {t}')
合并两个列表并去重
alist=set(map(int,input().split())) blist=set(map(int,input().split())) clist=alist|blist clist=list(clist) clist=sorted(clist) print(clist)
从多对中找到单身狗
方法一(直接法)
lst=list(map(int,input().split())) d={} for x in lst: d[x]=d.get(x,0)+1 for k in d: if d[k]==1: print(k) break
方法二(key和value对调)
lst=list(map(int,input().split())) d={} for x in lst: d[x]=d.get(x,0)+1 d1=dict(zip(d.values(),d.keys())) #字典键值互换 print(d1[1])
求列表中两数之和等于指定数的下标
- Given nums = [2, 11,7, 15], target = 9
- Because nums[0] + nums[1] = 2 + 7 = 9,
- print [0, 2].
比较不好的办法(o(n2))
lst=[2,11,7,15] for i in range(len(lst)): for j in range(i+1,len(lst)): if lst[i]+lst[j]==9: print(i,j) break
字典的方法(很好,o(n))
lst=[2,11,7,15] d={} for i in range(len(lst)): k=lst[i] if k in d: print(d[k],i) break d[9-k]=i
字典合并
输入用字符串表示两个字典,输出合并后的字典。字典的键用一个字母或数字表示。注意:1和‘1’是不同的关键字!
d1 = eval(input()) d2 = eval(input()) l1 = [] l2 = [] #定义cnt用于打印时判断是否到达列表结尾 cnt = 0 #循环.如果d1中有k键,那就值相加.如果没有就增加k键 for k in d2: d1[k] = d1.get(k, 0) + d2[k] #把d1中的键按类型分别加入两个列表,以便排序和控制输出是顺序 l1 = [k for k in d1 if type(k) == int] l2 = [k for k in d1 if type(k) == str] #排序 l1.sort() l2.sort() #合并排序后的列表到l1 l1 += l2 #按要求格式输出 print('{', end='') for i in l1: if type(i) == int: print('{}:{}'.format(i, d1[i]), end='') else: print('"{}":{}'.format(i, d1[i]), end='') if cnt < len(l1)-1: print(',',end='') cnt += 1 print('}')
字典的应用-找出出现次数最多的字符串
cnt={} while True: s=input() if s!='q': cnt[s]=cnt.get(s,0)+1 else: break cnt_order=sorted(cnt.items(),key=lambda x:x[1],reverse=True) a,b=cnt_order[0] print(f'{a} {b}')
字典的合并
d1=eval(input()) d2=eval(input()) for k in d2: d1[k]=d1.get(k,0)+d2[k] d1_order=sorted(d1.items(),key=lambda x:x[0],reverse=False) print(dict(d1_order))
字典合并、排序、打印
d1=eval(input()) d2=eval(input()) for k in d2: d1[k]=d1.get(k,0)+d2[k] d1_order=sorted(d1.items(),key=lambda x:x[0],reverse=False) d=dict(d1_order) for i in d: print(f'{i}:{d[i]}')