# Python 高级应用--第二章

2-1 如何在列表,字典和集合中根据条件筛选数据

实际案例:

1.过滤列表[1,2,3,-6,-2,7,9,10]中的负数。

初级方法

data=[1,2,3,-2,2,-6,8]
res=[]
for x in data:
if x>=0:
res.append(x)
print(res)

filter 函数

from random import randint
data=[randint(-10,10) for _ in range(10)]
print(data)
data1=list(filter(lambda x: x >= 0, data))
print(data1)

Notice 上面的代码中,randint 随机生成10个范围在-10到10之间的数。

filter 的第一个参数是用来筛选的函数,依次迭代传入的参数,然后被函数进行判断,返回布尔值,如果布尔值为真,则将这个值返回到最终的值,如果为假,就过滤掉。第二个参数是被筛选的数据在这里我们使用匿名函数来创建函数,筛选完之后的值要转换成列表才能进行输出。

列表解析:

from random import randint
data=[randint(-10,10) for _ in range(10)] #创建列表为[]
data1=[x for x in data if x >= 0]
print(data1)

列表解析和filter 函数比较,使用timeit 函数来对两个方法的运行时间进行计算:

timeit [x for x in data if x >= 0]
timeit filter(lambda x:x >= 0, data)

Notice 认为列表解析更快一点,我们首选的是列表解析。

2.对于字典中删除某些值对应的元素

示例:首先我们创建一个字典,键是20个同学的学号,值是每个同学的考试成绩。然后我们要根据值来筛选成绩在90分以上的同学。

from random import randint
d={x: randint(60,100) for x in range(1,21)}
print(d)
dd={k:v for k,v in d.items if v > 90}
print(dd)

Notice 字典解析中的一个重要方法是items()iteritems

items :将字典中所有的项,以列表的方式返回。因为字典是无序的,所有items 返回的项也是无序的。

iteritems :与items 的方法相同,但是返回的不是列表,而是迭代器。iteritems 方法在需要迭代结果的时候使用最合适,而且它的工作效率非常高。

总结:在Python2.x中,iteritems() 用于返回本身字典列表操作后的迭代器【Returns an iterator on all items(key/value pairs) 】,不占用额外的内存。

在Python 3.x 里面,iteritems()方法已经废除了。在3.x里用 items()替换iteritems() ,可以用于 for 来循环遍历。

  1. 筛选出集合中满足条件的元素

集合解析:找到集合中能被三整除的元素

from random import randint
data={randint(-10,10) for _ in range(10)} #创建集合为{}
data1={x for x in data if x % 3 == 0}
print(data1)

2-2 如何元组中的元素命名,提高程序的可读性。

学生信息系统中数据为固定格式:(名字,年龄,性别,邮箱地址)

学生数量很大为了减小存储开销,对每个学生信息用元组表示:

(‘Jim',16, 'male','[email protected]')

('Lilei',17,'male','[email protected]')

('Lucky',16,'female','[email protected]')

访问时,我们使用引索(index)访问,大量引索降低程序可读性,如何解决这个问题。所以我们将索引赋值给能够具体描述索引信息的变量。

student=('jim',16,'male','[email protected]')
NAME,AGE,SEX,EMAIL=range(4) #将数值分别赋值给四个变量
print(student[NAME])
if student[AGE]>=18:
print(student[NAME],student[AGE])
if student[SEX]=="male":
print(student[NAME],student[SEX])

下面使用类对象来对数据进行访问

from collections import namedtuple
student=namedtuple('Student',['name','age','sex','email'])# 创建一个名叫student的类
s=student("jim","16","male","[email protected]")# 创建一个student的实例对象
print(s)
print(s.name)#以属性来对s进行访问。
print(s.sex)
print(s.age)
print(isinstance(s,tuple))#检查我们创建的s是否确实是元组

2-3 如何统计出元素出现的频度

实际案列:

1.某随机序列[12,5,4,6,7,8,...]中,找到出现次数出现最多的元素。

知识拓展:

根据键或者值对字典进行排序:

from random import randint
data=[randint(0,20) for _ in range(30)]
print(data)
c=dict.fromkeys(data,0)
print(c)
for x in data:
c[x]+=1
print(c)
c_s=sorted(c.keys())
print(c_s)
c_ss=sorted(c.items(),key=lambda item:item[1])
print(c_ss)z

根据键来进行排序

d={'lilee':25,'wanyuan':21,'liqun':32}
sorted(d.keys())

根据值来进行排序

sorted(d.items(),key=lambda item:item[1])

使用Counter 函数来分析:将序列传入Counter 的构造器,得到Counter 对象是元素频数的字典。然后使用Counter.most_common() 方法得到频数最高的n个元素的列表。

from collections import Counter
from random import randint
data=[randint(0,20) for _ in range(30)]
c2=Counter(data) #统计每个数出现的频数,并返回字典,键是数字,值是数字出现的频数
print(c2)
print(c2.most_common(3))#输出出现次数最多的三个元素

2.对某英文文章的单词,进行词频统计,找到出现次数最高的10个单词,它们出现的次数是多少。

from collections import Counter
import re
file="English.txt" #创建一个文件
f=open(file,'w+') #打开文件
f.write("It's quite common those days for students in many contries to have break from studying after graduating from high school. This trend is not restricted for rich students who have money to trival, but is also evident for poorer students who choose to work or become economically independent for a period of time. This trend maybe involve the recognizatiion that young adult who passed directly from school to university is rather restricted in term of general knowledge and experience of the world. On the contrary, those who have spent some time earning a living or travel to other places, have a broader view of life and better personal resource to draw on. They tend to be more independent, which is a very important factor in academic study and research, and giving them an advantage in terms of dealing with the challenges of students' life.")#往文件中写入东西
f.close()# 关闭文件

file=open("English.txt","r")
text=file.read()
txtlist=re.split('\W+',text)#这里使用非单词的字符来进行分割,就可以吧一个一个的单词分开。
c3=Counter(txtlist) #将分割好的单词列表传递给Counter开始计数,最后以字典的形式返回
print(c3)
print(c3.most_common(3)) #输出频度最高的单词

2-4 如何根据字典中值的大小对字典中的项进行排序

实际案例:

某班英语成绩以字典的形式进行存储:{'lili':79,'lini':88,'dd':90}

现在要求根据成绩的高低,对学生进行排名。

使用python的内置函数sorted

from random import randint
d={x: randint(60,100) for x in 'xyzcfd'}
print(sorted(d)) #只是对键进行了排序,因为键是可迭代对象
print((97,'a') > (100,'b')) #对元组进行比较的时候,先比较低零个元素
socres=list(zip(d.values(),d.keys())) #zip可以对两个列表中的元素进行两两拼接,拼接为(value,key),就可以根据元组的比较来进行排序
print(scores)
print(sorted(scores))

利用sorted 函数的key 参数

from random import randint
d={x: randint(60:100) for x in 'xvgdkuf'}
print(d.items())
print(sorted(d.items(),key=lambda x: x[1])) #使用sorted的key参数时,我们构建一个匿名函数,因为每次穿进去的x值有两项,第零项是键也就是人名,不是我们需要比较的项,而我们需要比较的项是第二项分数,所有就取x[1]

2-5 如何快速找到多个字典中的公共键

实际案例:西班牙足球甲级联赛,每轮球员进球统计,然后统计出前N轮,每场比赛都有进球的球员。

方法一:对键进行迭代

from random import randint,sample
s1={x: randint(1,4) for x in sample('abcdefg', randint(3,6))}
s2={x: randint(1,4) for x in sample('abcdefg', randint(3,6))}
s3={x: randint(1,4) for x in sample('abcdefg', randint(3,6))}
print(s1)
print(s2)
print(s3)
res=[]
for k in s1:
if k in s2 and k in s3:
res.append(k)
print(res)

方法二:利用集合(set)的交集操纵:

  • Step1:使用字典的viewkeys()方法,得到一个字典keys的集合

  • Step2:使用map函数,得到所有的字典的keys 的集合

  • Step3:使用reduce函数,去所有字典的keys的集合的交集

from random import randint,sample
s1={x: randint(1,4) for x in sample('abcdefg',randint(3,6))}
s2={x: randint(1,4) for x in sample('abcdefg',randint(3,6))}
s3={x: randint(1,4) for x in sample('abcdefg',randint(3,6))}
print(s1)
print(s2)
print(s3)
print(s1.keys() & s2.keys() & s3.keys())

但是前面的方法只能针对比赛轮数少的人来说:

from functools import reduce #python3中将reduce函数放到了functools中
from random import randint,sample
s1={x: randint(1,4) for x in sample('abcdefg',randint(3,6))}
s2={x: randint(1,4) for x in sample('abcdefg',randint(3,6))}
s3={x: randint(1,4) for x in sample('abcdefg',randint(3,6))}
print(s1)
print(s2)
print(s3)
dd=list(map(dict.keys,[s1,s2,s3]))
print(list(reduce(lambda a,b: a & b, dd)))

2-6 如何让字典保持有序?

实际案列:某编程竞赛系统,对参赛选手编程解题进行计时,选手完成题目之后,把该选手解题用时记录到字典中,以便赛后安选手名字查询成绩(答题时间越短,成绩越优异)

{'li':(2,43),'mm':(5,52)....}

比赛结束后,需按照排名顺序依次打印选手的成绩,如何实现?

解决方案:使用collections.OrderedDict , 以OrderedDict 代替内置字典Dict,依次将选手的成绩存入OrderedDict。

# python内置的字典
d={}
d['Jim']=(1,35)
d['Leo']=(2,37)
d['Bob']=(3,40)
for k in d:
print(k) # python内置的字典会默认按照字母的先后顺序来进行输出,而不能发保证字典中的项按照输入的先后顺序来进行排序

使用collections下的OrderedDict来创建的字典:

d=OrderedDict()
d['Jim']=(1,35)
d['Leo']=(2,37)i
d['Bob']=(3,40)
for k in d:
print(k) # 此时输出的键就是按照输入字典的先后顺序来排列的

具体模拟比赛的过程:(file.py)

#!/usr/bin/python2
from time import time
from random import randint
from collections import OrderedDict
players=list('ABCDEFGH') #8个比赛成员用字母代替
start=time() #随机确定开始时间
d=OrderedDict() #创建一个可以排序的字典
for i in xrange(8):
raw_input() #根据输入的事件不同,来等待时间
p=players.pop(randint(0,7-i)) #随机取出player列表中的人名
end=time() 取结束后的时间
print i + 1, p, end-start,
d[p]=(i + 1, end-start)
print("\n")
print("-" * 20)
for k in d:
print k,d[k]

如何实现用户的历史记录功能(最多有n条)

很多应用程序都有浏览用户记录的功能,例如:

浏览器可以查看最近访问的网页

视频播放器可以查看最近播放过的视频文件

Shell可以查看用户输入过的命令

。。。。。。

我们现在制作了一个简单的猜数字小游戏,然后添加历史记录的功能,显示用户最近添加过的数字:

实现过程:

使用容量为n的队列存储历史记录:

使用标准库collections中的deque, 它是一个双端循环队列。

程序退出前,可以使用pickle将队列对象存入文件,再次运行程序时将其导入

#!/usr/python2
from random import randint
from collections import deque
import pickle
history=deque([],5) #创建一个空的双端队列,然后在之后使用append方法将输入过的值添加到里面去
N = randint(0,100)
def guess(k):
if k == N:
print('right')
return True
if k < N:
print('%s is less than N')
else:
print('%s is greater than N')
return False

while True:
line=raw_input('please input a number:')
if line.isdigit():
k=int(line)
history.append(k)
if guess(k):
break
elif line == 'history' or line == 'h?': #当我们输入特定history的时候就会跳出历史输入记录
print(list(history))
pickle.dump(history,open('history','w'))
q=pickle.load(open('history'))
print(q)

Notice collections 中的双端队列能够不断更新队列中的内容

你可能感兴趣的:(# Python 高级应用--第二章)