python 实用编程技巧 —— 数据结构与算法
如何在列表, 字典, 集合中根据条件筛选数据
过滤列表中的负数
使用列表解析方法
from random import randint data = [randint(-10,10) for _ in range(10)] print(data) print(list(filter(lambda x:x>=0,data)))
使用 filter 函数
from random import randint data = [randint(-10,10) for _ in range(10)] print(data) print(list(filter(lambda x:x>=0,data)))
找出分数大于90的学生
字典解析方法
from random import randint d = {x:randint(60,100) for x in range(1,21)} list(filter(lambda x:x[1] > 90, d.items()))
使用 filter 函数
[filter(lambda item: item[1] >= 90, d.items())]
留下集合中的3的倍数
from random import randint s = {randint(0,20) for _ in range(20)} list(filter(lambda x:x%3==0, s))
如何为元组中的每个元素命名, 提高程序可读性
定义一系列数值常量或枚举类型
NAME, AGE, SEX, EMAIL = range(4) student = ('Jim', 16, 'male', 'jim8721@gmail.com') print(student[NAME]) print(student[AGE]) print(student[SEX]) print(student[EMAIL])
使用 python3 中的枚举类型
from enum import IntEnum class StudentEnum(IntEnum): NAME = 0 AGE = 1 SEX = 2 EMAIL = 3 print(student[StudentEnum.NAME]) print(student[StudentEnum.AGE]) print(student[StudentEnum.SEX]) print(student[StudentEnum.EMAIL])
使用标准库中 collections.namedtuple 替代内置tuple
from collections import namedtuple Student = namedtuple('Student', ['name', 'age', 'sex', 'email']) s2 = Student('Jim', 16, 'male', 'jim8721@gmail.com') print(s2.name) print(s2.age) print(s2.sex) print(s2.email)
如何统计序列中元素的出现频度
将序列转化为字典{元素: 频度}, 根据字典中的值排序
from random import randint data = [randint(0,20) for _ in range(30)] #fromkeys:用于创建并返回一个新的字典。两个参数:第一个是字典的键,第二个(可选)是传入键的值,默认为None。 c = dict.fromkeys(data,0) for x in data: c[x] += 1 # 如果只是想取出最大的3个,可以使用堆代替排序后再取值的方法 import heapq res2 = heapq.nlargest(3, ((v,k) for k,v in c.items())) print(res2)
使用标准库collections中的Counter对象
from collections import Counter from random import randint data = [randint(0,20) for _ in range(30)] c2 = Counter(data) #找出频率出现最高的3个元素 print(c2.most_common(3))
实际运用: 词频统计
from collections import Counter import re txt = open('example.txt').read() # 读入文件 wordList = re.split('\W+', txt) c2 = Counter(wordList) # 可以传入列表或者字典 res4 = c2.most_common(10) print(res4)
如何根据字典中值的大小, 对字典中的项排序
元祖进行比较,先比较第一个元素,在比较第二个元素
# 元祖进行比较,先比较第一个元素,在比较第二个元素 print((97, 'a') > (96, 'b')) print((97, 'a') > (97, 'b'))
利用zip将字典转换成元组进行排序
from random import randint d = {x:randint(60,100) for x in 'xyzabc'} print(d) print(sorted(zip(d.values(),d.keys())))
传递sorted函数的key参数
from random import randint d = {x:randint(60,100) for x in 'xyzabc'} print(sorted(d.items(),key=lambda x:x[1]))
如何快速找到多个字典中的公共键(key)
random 函数取样
from random import randint,sample # 取样 print(sample('abcdef',3)) # 随机去 3 个
方案一: 利用集合的交集操作
from random import randint,sample # 取样 s1 = {x:randint(1,4) for x in sample('abcdef',randint(3,6))} s2 = {x:randint(1,4) for x in sample('abcdef',randint(3,6))} s3 = {x:randint(1,4) for x in sample('abcdef',randint(3,6))} print(s1) print(s2) print(s3) print('resuit ===========') print(s1.keys() & s2.keys() & s3.keys())
方案二: 使用map和reduce
- step1 使用字典的keys方法, 得到一个字典keys的集合
- step2 使用map函数, 得到每个字典keys的集合
- step3 使用reduce函数, 取所有字典的keys集合的交集
from random import randint,sample from functools import reduce s1 = {x:randint(1,4) for x in sample('abcdef',randint(3,6))} s2 = {x:randint(1,4) for x in sample('abcdef',randint(3,6))} s3 = {x:randint(1,4) for x in sample('abcdef',randint(3,6))} dl = [s1, s2,s3] print(s1) print(s2) print(s3) print('result======') print(reduce(lambda a, b: a & b, map(dict.keys, dl)))
如何让字典保持排序
使用标准库collections 中的OrderedDict
为了能控制一个字典中元素的顺序,你可以使用 collections
模块中的 OrderedDict
类。 在迭代操作的时候它会保持元素被插入时的顺序
from collections import OrderedDict d = OrderedDict() d['foo'] = 1 d['bar'] = 2 d['spam'] = 3 d['grok'] = 4 # Outputs "foo 1", "bar 2", "spam 3", "grok 4" for key in d: print(key, d[key])
如何实现用户的历史记录功能(最多n条)
使用容量为n的 队列存储历史记
- 使用标准库collections中的deque, 它是一个双端循环队列
- 使用pickle模块将历史记录存储到硬盘, 以便下次启动使用(代替数据库)
from random import randint from collections import deque N = randint(0, 100) history = deque([], 5) def guess(k): if k == N: print('Right') return True if k < N: print('%s is less-than N' % k) else: print('%s is greater-than N' % k) return False while True: line = input('Please input a number:') if line.isdigit(): k = int(line) history.append(k) if guess(k): break elif line == 'history' or line == 'h': print(list(history))
plckle 基本使用
from collections import deque import pickle q = deque([2, 3, 4, 5, 6]) print(q) # 将数据存入文件 pickle.dump(q,open('history','wb')) # 读取文件 q2 = pickle.load(open('history','rb')) print(q2)