问题:在迭代操作或者其他操作的时候,怎样只保留最后有限几个元素的历史记录?
解决方案:保留有限历史记录正是 collections.deque 大显身手的时候。比如,下面的代码
在多行上面做简单的文本匹配,并返回匹配所在行的最后 N 行:
1 # 在多行上面做简单的文本匹配,并返回匹配所在行的最后 N 行: 2 3 from collections import deque 4 5 def search(lines, pattern, history=5): 6 previous_lines = deque(maxlen=history) 7 for line in lines: 8 if pattern in line: 9 yield line, previous_lines 10 previous_lines.append(line) 11 12 # Example use on a file 13 if __name__ == '__main__': 14 with open(r'exam.txt') as f: 15 for line, prevlines in search(f, 'python', 5): 16 for pline in prevlines: 17 print(pline, end='') 18 print(line, end='') 19 print('=' * 20) 20 21
问题:怎样从一个集合中获得最大或者最小的 N 个元素列表?
解决方案:heapq 模块有两个函数: nlargest() 和 nsmallest() 可以完美解决这个问题。
1 import heapq 2 3 nums = [1, 8, 2, 5, 23, 18, 6, 9, -4] 4 print(heaq.nlargest(3, nums)) 5 print(heaq.nsmallest(3, nums)) 6 7 portfo = [ 8 {'name': 'IBM', 'shares': 100, 'price': 91.1}, 9 {'name': 'AAPL', 'shares': 50, 'price': 543.22}, 10 {'name': 'FB', 'shares': 200, 'price': 21.09}, 11 {'name': 'HPQ', 'shares': 35, 'price': 31.75}, 12 {'name': 'YHOO', 'shares': 45, 'price': 16.35}, 13 {'name': 'ACME', 'shares': 75, 'price': 115.65}] 14 15 # 在对每个元素进行对比的时候,会以 price 的值进行比较。 16 # lambda匿名函数表达式是起到一个函数速写的作用,允许在代码内嵌入一个函数的定义 17 cheap = heapq.nsmallest(3, protfo, key=lambda s: s['price']) 18 expensive = cheapq.nlargest(3, protfo, key=lambda s: s['price'])
当要查找的元素个数相对比较小的时候,函数 nlargest() 和 nsmallest() 是很
合适的。如果你仅仅想查找唯一的最小或最大(N=1)的元素的话,那么使用 min() 和
max() 函数会更快些。类似的,如果 N 的大小和集合大小接近的时候,通常先排序这个
集合然后再使用切片操作会更快点(sorted(items)[:N] 或者是 sorted(items)[-N:]
)。需要在正确场合使用函数 nlargest() 和 nsmallest() 才能发挥它们的优势(如果
N 快接近集合大小了,那么使用排序操作会更好些)。