1.数据结构和算法
1.1 输出文本中匹配的内容的行以及前几行
#!/usr/bin/env python from collections import deque def search(lines,pattern,history=5): previous_lines = deque(maxlen=history) for line in lines: if pattern in line: yield line,previous_lines previous_lines.append(line) if __name__ == '__main__': with open('55555.txt') as f: for line,previous_lines in search(f, 'python', 3): for pline in previous_lines: print(pline,end='') print(line) print('-'*20)
1.2取N个最大和最小值
import heapq list1 = [1,-3,55,-44,0] print(heapq.nlargest(3, list1)) print(heapq.nsmallest(3, list1)) #当所要找的元素个数相对较小时,函数nlargest()和nsmallest()才是最合适的。 #如果要找的元素个数与集合本身差不多大的话,通常更快的方法是先对集合排序再切片。(sorted(list1)[:N] or sorted(list1)[-N:]) print(min(list1)) print(max(list1)) #如果只查询最大或者最小的一个值,还是用min()和max()更快。
1.3 对字典的数据排序
prices = { 'a':123, 'b':456, 'd':559, 'f':865 } print(min(zip(prices.values(),prices.keys())))
(123, 'a') #如果尝试在字典上执行常见的数据操作,将会发现它们只会处理键,而不是值。 #为了能对字典内容做些有用的计算,通常会利用zip()将字典的键和值反转过来。
1.4 在两个字典间处理异同
dict_a = { 'x':1, 'y':2, 'z':3 } dict_b = { 'a':1, 'b':2, 'y':3 } print(dict_a.keys() & dict_b.keys()) #a和b都有的键 print(dict_a.keys() - dict_b.keys()) #去掉a中有b的键 print(dict_a.items() - dict_b.items()) #去掉a中有b的键值的item。 c = {key:dict_a[key] for key in dict_a.keys() - ['z','x']} print(c) #结果: {'y'} {'x', 'z'} {('z', 3), ('y', 2), ('x', 1)} {'y': 2}
1.5 从序列中移除重复项且保持元素间顺序不变
如果无需保证元素间顺序不变,可以a = [1,21,2,2,1,3,5],然后set(a)就可以去重。
如果要保证元素间顺序不变,见下:
a = [1,2,3,4,5,5,4,3,2,1] #序列中的元素必须是可哈希(在生存周期内不可变)的 def deqeue(items): seen = set() for item in items: if item not in seen: yield item seen.add(item) print(list(deqeue(a))) #结果: [1, 2, 3, 4, 5] #如果序列中的元素是不可哈希的,就得用下面的代码了, a = [1,2,3,4,5,5,4,3,2,1] b = [{'x':1,'y':2},{'x':1,'y':3},{'x':2,'y':2},{'x':1,'y':3},{'x':4,'y':3},] def duqeue(items,key=None): seen = set() for item in items: val = item if key is None else key(item) if val not in seen: yield val seen.add(val) print(list(duqeue(a))) print(list(duqeue(b, key=lambda d:(d['x'],d['y'])))) #结果: [1, 2, 3, 4, 5] [(1, 2), (1, 3), (2, 2), (4, 3)]
1.12 找出序列中出现次数最多的元素
from collections import Counter a = [1,2,3,4,5,5,4,3,2,1,1,1,1,2,3,3,4] counters = Counter(a) print(counters[4]) print(counters[1]) print(counters.most_common(3)) #结果: 3 #4出现了3次 5 #1出现了5次 [(1, 5), (3, 4), (2, 3)] #按出现次数从大到小前三位
1.13 通过公共键对字典列表排序
from operator import itemgetter rows = [ {'fname':'Brian','lname':'fsaf','uid':432432}, {'fname':'Zrian','lname':'ssaf','uid':132432}, {'fname':'Crian','lname':'zsaf','uid':332432} ] rows_by_fname = sorted(rows, key=itemgetter('fname')) rows_by_uid = sorted(rows, key=itemgetter('uid')) print(rows_by_fname) print(rows_by_uid) #结果: [{'uid': 432432, 'fname': 'Brian', 'lname': 'fsaf'}, {'uid': 332432, 'fname': 'Crian', 'lname': 'zsaf'}, {'uid': 132432, 'fname': 'Zrian', 'lname': 'ssaf'}] #按fname的开始字母排序的 [{'uid': 132432, 'fname': 'Zrian', 'lname': 'ssaf'}, {'uid': 332432, 'fname': 'Crian', 'lname': 'zsaf'}, {'uid': 432432, 'fname': 'Brian', 'lname': 'fsaf'}] #按uid的大小排序的
rows_by_fname_lambda = sorted(rows, key = lambda r:r['fname'])
rows_by_uid_lambda = sorted(rows, key = lambda r:(r['uid'],r['fname'])) ,利用lambda也能实现,只是效率不如用itemgetter高。
1.14 对不原生支持比较操作的对象排序
class User: def __init__(self,user_id): self.user_id = user_id def __repr__(self): return 'User({})'.format(self.user_id) u = [User(17),User(27),User(3)] print(sorted(u,key = lambda u:u.user_id)) #结果: [User(3), User(17), User(27)]
直接排序User(17),User(27),User(3)是会报错的。
1.16 筛选序列中的元素
a = [1,-1,2,0,33,4,-22] print([n for n in a if n > 0]) #这样可以做到,但是如果原始数据非常大的话,这么做可能会产生一个庞大的结果。如果这是你需要考虑的问题,那么可以使用生成器表达式通过迭代的方式产生筛选的结果。 pos = [n for n in a if n > 0] for x in pos: print(x) 有时候以为生成器的语法太简单而不足以满足需求,可以自定义一个筛选函数,然后结合filter筛选, b = [1,-1,2,0,33,4,-22,'fdsaf'] def val_filter(num): try: x = int(num) return True except ValueError: return False ivals = list(filter(val_filter,b)) print(ivals)