转载的老板请注明出处:http://blog.csdn.net/cc_xz/article/details/78691928万分感谢!
在本篇中,你将了解到:
1.如何在字典、列表、集合中筛选数据。
2.统计列表中元素的出现频次。
3.对容器中的值进行排序。
4.字典的多种应用方法。
列表, 字典, 集合中根据条件筛选数据:
请思考:
过滤掉列表:list = [3,9,-1,10,20,-2]中的负数
筛选出字典:{'LiLei':79,'Jim':88,'Lucy':92}中值高于90的项
筛选出集合:{77,89,32,20}中能被3整除的元素
最简单的方法是依次迭代列表、字典、集合中的每个项,然后使用条件判断,符合添加,则将值添加到新列表中,如果不符合,则继续迭代。例如:
oldList = [3,9,-1,10,20,-2]
newList = []
for value in oldList:
if value < 0 :
newList.append(value)
print(newList)
输出结果为:
[-1, -2]
但除上述代码外,还有更简洁高效的方法。例如,列表可以使用filter函数和列表解析。字典和集合可以分别使用字典解析和集合解析。
使用列表解析筛选列表:
from random import randint
import timeit
"""
列表推导式:
@randint 用于生成随机数,起始范围是-10,结束是10。
@range 生成从0-9的数,用于占位操作。
此段代码的作用是:生成的列表有10个元素,而元素的值是通过randint生成的随机数。
"""
list = [randint(-10, 10) for value in range(10)]
print(list)
"""
首先将list中的值通过for遍历逐个取出,赋值给第二个x,然后通过if判断,如果结果为True,则将x(第一个)的值放入列表中,如果不为真,则继续遍历、判断。
"""
result = [x for x in list if x >= 0]
print(result)
"""
timeit函数:
此函数用于返回推导式执行的时间,第一个参数为执行的推导式。但此推导式中使用到了外部包,而导入外部包的代码在setup=参数中使用字符串表示。
number表示代码执行的次数。当timeit函数执行完毕后,会返回一个值,是执行代码的耗时,以秒为单位。
"""
print(timeit.timeit('[randint(-10, 10) for value in range(10)]',setup='from random import randint' ,number=100000))
输出结果为:
[5, -7, -4, -10, 4, -4, -3, -4, 10, 9]
[5, 4, 10, 9]
1.9519859145993275
使用字典解析筛选字典:
from random import randint
"""
同列表生成式不同的是,在最前端,使用通过range()生成的从1-20的值作为字典的Key,
而Value使用randint()生成的随机数。在将Key和Value放入字典中时,直接使用了x:randint()。
"""
dict = {x:randint(60,100) for x in range(1,20)}
print(dict)
"""
首先使用dict.items()将字典中所有的key和value都取出,然后判断value的值,如果大于等于90,
则将当前的key和value放入新字典中,再继续执行循环。
"""
dict01 = {k:v for k,v in dict.items() if v >= 90}
print(dict01)
输出结果为:
{1: 60, 2: 95, 3: 88, 4: 96, 5: 80, 6: 98, 7: 81, 8: 84, 9: 92, 10: 74, 11: 100, 12: 99, 13: 78, 14: 97, 15: 83, 16: 87, 17: 71, 18: 89, 19: 85}
{2: 95, 4: 96, 6: 98, 9: 92, 11: 100, 12: 99, 14: 97}
使用集合解析筛选集合:
from random import randint
import timeit
set = {randint(1,100) for x in range(10)}
print(set)
set01 = {x for x in set if x % 3 == 0}
print(set01)
输出结果为:
{4, 75, 78, 81, 49, 20, 21, 85, 30}
{81, 75, 21, 78, 30}
使用列表解析筛选列表:
myList = ['cangL',21,'男','754003@qq.com']
在上述代码中,如果我们希望访问某个元素,则需要使用index来访问,但在代码中大规模的使用数字为index,则会导致程序的可读性降低。第一种解决方案如下:
myList = ['cangL',21,'男','[email protected]']
NAME,AGE,SEX,EMAIL = range(4)
print(myList[EMAIL])
输出结果为:
754003@qq.com
统计出出现频度:
统计随机序列中的频次 :
from random import randint
from collections import Counter
myList = [randint(1,10) for x in range(50)] #创建一个长度为50,值是1-10的随机数的列表。
print(myList)
myDict = Counter(myList) #生成一个Dict(字典),键(Key)为列表中的值,值(Value)为列表中的值出现的次数。
print(myDict)
print(myDict.most_common(3)) #筛选出出现次数最多的3个Key/Value
输出结果为:
[10, 7, 5, 3, 6, 6, 2, 4, 1, 5, 6, 4, 5, 3, 6, 3, 3, 9, 7, 1, 10, 4, 1, 6, 9, 3, 5, 7, 1, 5, 9, 4, 4, 2, 4, 7, 1, 2, 9, 9, 8, 3, 5, 3, 4, 7, 8, 10, 7, 4]
Counter({4: 8, 3: 7, 5: 6, 7: 6, 1: 5, 6: 5, 9: 5, 2: 3, 10: 3, 8: 2})
[(4, 8), (3, 7), (5, 6)]
在文章中统计单词频率:
from collections import Counter
import re
text01 = open('C:/test.txt').read() # 首先打开一个文档,read()表示以字符串的形式将文档返回。
text02 = re.split('\W+', text01) # 使用正则表达式,将所有单词字符分割出来,需要分割的变量是text01
text03 = Counter(text02) # 将分割出的单词作为字典,单词本身作为Key,出现的次数作为Value。
print(text03)
text = Counter(re.split('\W+', open('C:/test.txt').read())) #一行代码将上述代码整合。
print(text)
输出结果为:
Counter({'self': 1356, 'def': 875, 'signature': 875, 'real': 825, 'unknown': 807, 'pass': 746,..........
Counter({'self': 1356, 'def': 875, 'signature': 875, 'real': 825, 'unknown': 807, 'pass': 746,..........
以上结果省略......太多了....
针对容器中的值进行排序:
zip()函数:
zip()函数接受任意数量的列表作为参数,将列表组合为tuple(元组)。示例如下:
from random import randint
list01 = [randint(0,10) for x in range(8)]
list02 = [randint(0,10) for x in range(5)]
list03 = [randint(0,10) for x in range(5)]
list04 = [randint(0,10) for x in range(3)]
tuple01 = zip(list01,list02,list03,list04) #zip()实际上返回的是一个对象
for x in tuple01:
print(x)
print(tuple01)
输出结果为:
(6, 9, 10, 6)
(3, 1, 1, 2)
(8, 10, 3, 8)
object at 0x0000000002782608>
由于zip()函数输出的是一个Object格式的对象,但此对象是可以被遍历的,所以通过for循环可以输出其中的结果。当然,也可以在使用print()函数输出zip()返回值时将该列表转换为list()。此外,当传入参数的长度不同时,zip()会自动以最短序列长度为准进行截取,以获得元组。
使用zip()配合sorted()对字典排序:
from random import randint
dict01 = {x: randint(10,20) for x in range(5)}
print(dict01)
tuple01 = zip(dict01.values(),dict01.keys()) #在生成tuple(元组)时,将字典的值放在前方,因为sorted()函数优先使用第一位值排序,当第一位的值相等时,再根据后面的值排序。
print(tuple01)
tuple02 = sorted(tuple01,reverse=True)
print(tuple02)
输出结果为:
{0: 15, 1: 10, 2: 10, 3: 13, 4: 16}
<zip object at 0x0000000000C09808>
[(16, 4), (15, 0), (13, 3), (10, 2), (10, 1)]
使用sorted()的key参数排序:
from random import randint
dict01 = {x: randint(10, 20) for x in range(5)}
print(dict01)
"""
sorted()函数的key参数可以接收自定义的键值,即,在一个列表、字典等容器中自己选出用于比较的键值。
而这种实现方式往往使用匿名函数来完成,lambda是创建一个匿名函数。
x:表示key=x: PS:“:”表示从x开始直至结束。x[1]表示是使用x中的第二位值来做key对比。
而实际上,x=dict01.items()
reverse用于定义sorted()的排序方式,默认是最小的值在前,即:默认reverse=False。
而reverse=True表示最大的值在前。
"""
dict02 = sorted(dict01.items(), key=lambda x: x[1], reverse=True)
print(dict02)
输出结果为:
{0: 13, 1: 16, 2: 15, 3: 10, 4: 10}
[(1, 16), (2, 15), (0, 13), (3, 10), (4, 10)]
快速找到字典中的公共键:
公共键是值在一个程序中拥有多个字典,而每个字典中都包含的键(Key)被称为公共键。
使用for循环找出公共键:
from random import randint,sample
#此Demo模拟足球的进球数,一共5轮比赛,而8名球员,每轮会有3-5名球员进球,每进球的球员每场可能会进1-4个球。
"""
sample函数用于随机取值,即在字符串、列表、元组等容器中随机取出一个值。
在推导式中,首先使用sample在姓中随机取出一个值,并将值赋给x,而字典的长度为3-5的随机数。
接着将x的值作为字典的键(Key),而值取一个1-3的随机数。
"""
s1 = {x: randint(1,3) for x in sample('赵钱孙李周吴郑王',randint(3,5))}
s2 = {x: randint(1,3) for x in sample('赵钱孙李周吴郑王',randint(3,5))}
s3 = {x: randint(1,3) for x in sample('赵钱孙李周吴郑王',randint(3,5))}
s4 = {x: randint(1,3) for x in sample('赵钱孙李周吴郑王',randint(3,5))}
s5 = {x: randint(1,3) for x in sample('赵钱孙李周吴郑王',randint(3,5))}
print(s1,"\n",s2,"\n",s3,"\n",s4,"\n",s5)
res = [] #创建一个空列表,用于放置5轮比赛都进球的人。
for x in s1.keys(): #使用字典做递归,字典默认选取Key()作为递归值。
#每次循环都通过if判断,当前(s1)轮进球的球员,在其他4轮中是否进球(其他4个字典中是否包含该球员的名字(好吧实际上只有姓)
if x in s2 and x in s3 and x in s4 and x in s5:
res.append(x) #将选择出的球员(公共键Key)放到专门的列表中。
print(res) #而很大的概率该列表仍然是空的。
输出结果为:
{'周': 2, '孙': 2, '赵': 2, '钱': 3, '李': 2}
{'孙': 2, '郑': 1, '李': 3}
{'周': 3, '孙': 2, '李': 3}
{'周': 2, '孙': 2, '钱': 2, '郑': 1}
{'周': 2, '孙': 3, '钱': 1}
['孙']
map()函数的使用:
map()函数接受两个参数,一个是函数,另一个是可迭代的对象,可以是列表、元组、字典等。map会将可迭代对象中的元素,依次放入到函数中执行,再将执行的结果作为map对象返回。请看如下案例:
list01 = [1, 2, 3, 4, 5, 6, 7, 8]
def test(x): #函数将传入的值+10,并输出当前被传入的值。
print("x = ", x)
return x + 10
list02 = list(map(test,list01))#将map返回的map对象转换为list
print(list02)
输出结果为:
x = 1
x = 2
x = 3
x = 4
x = 5
x = 6
x = 7
x = 8
[11, 12, 13, 14, 15, 16, 17, 18]
通过上述代码可以发现,验证了前面的理论:map()函数会将传入的可迭代对象(容器)的值依次传递到函数中执行,再将返回的新值组合成一个map对象。
map()作为高阶函数,事实上它将运算规则抽象化了,因此我们不但可以使用map()计算简单的加法,也可以将任何元素交到一个复杂的函数中去执行,例如下述案例中,将所有的数字转化为字符串:
list01 = list(map(str,[1, 2, 3, 4, 5, 6, 7, 8]))
print(list01)
输出结果为:
['1', '2', '3', '4', '5', '6', '7', '8']
使用map()并行处理:
list01 = [1, 2, 3, 4, 5]
list02 = [10, 20, 30, 40]
list03 = [100, 200, 300, 400, 500]
def test(x, y, z): # 函数会接受3个参数,并在内部进行处理。
print("x = ", x)
print("y = ", y)
print("z = ", z)
return x * 10, y * 10, z * 10
# 凡事函数同传入的容器相符,都可以使用map进行迭代操作。
list04 = list(map(test, list01, list02, list03))
print(list04)
输出结果为:
x = 1
y = 10
z = 100
.....省略部分结果
x = 4
y = 40
z = 400
[(10, 100, 1000), (20, 200, 2000), (30, 300, 3000), (40, 400, 4000)]
在每个list中,如果存在相同的下标,则会抽取出对应的元素,再执行传入的函数。如果下标不相同,则会执行至最短的下标处。如上案例,list02中只有4个元素,所以在执行test()函数时,只对所有的list的前4个元素进行处理。
reduce()函数的使用:
reduce()函数被称为化简函数,reduce()函数用于将一个数据容器(列表、字典、元组等)中的所有数据进行操作。reduce()会将传入的可迭代对象的第1个和第2个元素交由传入的函数中进行处理,再将得到的结果同可迭代对象的第3个元素传入函数中处理(通过自定义函数处理),以此类推,直至得到一个结果。
from random import randint
from functools import reduce
def test(x,y):
print("x=", x, end=" ------ ")
print("y=", y)
return x
list01 = [randint(1,3) for x in range(10)]
set01 = reduce(test,list01)
print(list01)
输出结果为:
x= 2 ------ y= 1
x= 2 ------ y= 3
x= 2 ------ y= 3
x= 2 ------ y= 2
x= 2 ------ y= 2
x= 2 ------ y= 3
x= 2 ------ y= 2
x= 2 ------ y= 2
x= 2 ------ y= 3
[2, 1, 3, 3, 2, 2, 3, 2, 2, 3]
在上述代码中,通过test()函数中的print()输出发现,在使用reduce()函数迭代列表时,列表会传入两个参数,但第一个参数(x)永远是列表中的第一个元素,而第二个参数(y)会随着每次迭代的增加,遍历列表中其余的元素。
通过reduce()找到公共键:
from random import randint, sample
from functools import reduce
#此Demo模拟足球的进球数,一共5轮比赛,而8名球员,每轮会有3-5名球员进球,每进球的球员每场可能会进1-4个球。
s1 = {x: randint(1, 3) for x in sample('赵钱孙李周吴郑王', randint(3, 5))}
s2 = {x: randint(1, 3) for x in sample('赵钱孙李周吴郑王', randint(3, 5))}
s3 = {x: randint(1, 3) for x in sample('赵钱孙李周吴郑王', randint(3, 5))}
s4 = {x: randint(1, 3) for x in sample('赵钱孙李周吴郑王', randint(3, 5))}
s5 = {x: randint(1, 3) for x in sample('赵钱孙李周吴郑王', randint(3, 5))}
print(s1,"\n",s2,"\n",s3,"\n",s4,"\n",s5)
def test(a, b):
print("a=", a, end=" ------ ")
print("b=", b)
return a & b
set02 = reduce(test,map(dict.keys, [s1, s2, s3, s4, s5]))
print(set02)
输出结果为:
{'王': 2, '周': 1, '李': 1, '赵': 3, '孙': 1}
{'赵': 2, '郑': 3, '李': 2, '孙': 2}
{'郑': 2, '钱': 1, '李': 1, '王': 2}
{'吴': 3, '钱': 3, '赵': 2, '王': 1, '李': 2}
{'王': 1, '周': 3, '郑': 1, '赵': 2, '李': 2}
a= dict_keys(['王', '周', '李', '赵', '孙']) ------ b= dict_keys(['赵', '郑', '李', '孙'])
a= {'李', '赵', '孙'} ------ b= dict_keys(['郑', '钱', '李', '王'])
a= {'李'} ------ b= dict_keys(['吴', '钱', '赵', '王', '李'])
a= {'李'} ------ b= dict_keys(['王', '周', '郑', '赵', '李'])
{'李'}
使字典保持有序:
from random import sample
from collections import OrderedDict
from time import time
StartTime = time() #记录开始时间。
NameList = [x for x in sample("赵钱孙李周吴郑王冯陈", 10)] #将参赛者打乱顺序放入到列表中。
OrderedDict01 = OrderedDict() #创建可以保持顺序的字典。
for x in range(len(NameList)): #将列表的长度转化为可迭代的对象。
input() #捕捉用户的输入,以此作为延时。
EndTime = str(round(time() - StartTime,3))+"秒" #处理耗时,首先使用当前时间减开始时间得出耗时,再四舍五入保留3位,最后转换成字符串。
print(NameList[x],"是第",x+1,"名,耗时:",EndTime) #打印结果,注意,由于列表的下标从0开始,所以排名要+1。
OrderedDict01[NameList[x]] = (x + 1, EndTime) #添加到字典中。
print(OrderedDict01)
输出结果为:
孙 是第 1 名,耗时: 1.547秒
李 是第 2 名,耗时: 2.245秒
冯 是第 3 名,耗时: 2.805秒
吴 是第 4 名,耗时: 3.842秒
郑 是第 5 名,耗时: 4.252秒
陈 是第 6 名,耗时: 4.927
赵 是第 7 名,耗时: 5.398秒
周 是第 8 名,耗时: 5.872秒
王 是第 9 名,耗时: 6.388秒
钱 是第 10 名,耗时: 6.873秒
OrderedDict([('孙', (1, '1.547秒')), ('李', (2, '2.245秒')), ('冯', (3, '2.805秒')), ('吴', (4, '3.842秒')), ('郑', (5, '4.252秒')), ('陈', (6, '4.927秒')), ('赵', (7, '5.398秒')), ('周', (8, '5.872秒')), ('王', (9, '6.388秒')), ('钱', (10, '6.873秒'))])
实现对象状态缓存:
from random import randint
from collections import deque
import pickle # 用于将对象存储到本地,或从本地读取对象。
number01 = randint(1, 20) # 创建一个1-20的随机数。
print("随机产生一个1-20的数,请猜一猜这个数是多少。")
# 使用try/except代替if判断当前情况(默认打开本地不存在的文件会报FileNotFoundError异常。
try:
# 新建一个缓存对象,首先用pickle读取本地文件,若不存在该文件,则报出异常,则执行except作用域中的代码(r为读取,b为读写二进制文件)。
cacheQueue = pickle.load(open("cacheQueue","rb"))
print("(已读取本地缓存文件。)")
except FileNotFoundError:
cacheQueue = deque([], 5) # 创建用于缓存猜数的队列,先定义初始值,再定义队列的长度。
print("(已新建本地缓存对象。)")
# 创建一个函数,用于输出缓存队列,但由于缓存队列是以对象的形式存在的,所以在输出时需要转换为list。
def Queue():
print(list(cacheQueue))
# 无限执行的循环,只有当匹配某条件时,才会跳出循环。
while True:
test = input() # 获取当前用户输入的字符串。
if test == "?": # 如果用户输入的值等于"?"则输出缓存队列。
Queue()
continue # 然后重新开始循环。
try: # 使用try捕捉异常,如果用户输入非数字的字符串,则抛出异常并重新开始循环。
number02 = int(test)
except ValueError: # "?"已经在前面的if中被捕捉。
print("猜数当然要输入数字啦!")
continue
if number02 > 20: # 如果输入的值大于20,则重新开始循环。
print("最大值是20好伐?")
continue
cacheQueue.append(number02) # 现已将"?"、非数字字符串和大于20的非法值排除,所以将本次猜数结果放如缓存队列中。
if number01 > number02:
print("猜错拉,你猜的数太小了。")
continue
elif number01 < number02:
print("猜错拉,你猜的数太大了。")
continue
elif number01 == number02:
print("猜对啦,正确结果是:", number02)
pickle.dump(cacheQueue, open("cacheQueue", "wb+"))
break # 最后猜中正确结果时,跳出循环。程序结束。
输出结果为:
随机产生一个1-20的数,请猜一猜这个数是多少。
(已读取本地缓存文件。)
?
[10, 5]
10
猜错拉,你猜的数太小了。
15
猜错拉,你猜的数太小了。
18
猜对啦,正确结果是: 18