Python Cookbook 2 ——搜索和排序
来源:互联网 发布:sql 列出表中所有字段 编辑:程序博客网 时间:2024/06/03 20:22
Donald Knuth教授曾在《 The Art of Computer Programming》中提到:有很多计算机花了超过一半的计算时间在排序上。可以理解为:
- 确实有很多非常重要的和排序有关的应用;
- 有很多人在进行一些不必要的排序;
- 低效的排序算法被广泛应用造成了计算时间的浪费。
在Python中,对于排序的策略:
- 当需要排序的时候,尽量设法使用内建Python列表的sort方法;
- 当需要搜索的时候,尽量设法使用内建的字典。
最常用的是decorate-sort-undecorate(DSU)模式,这是一种通用的方法:通过创建一个辅助的列表,将问题转化为列表的排序,从而可以使用默认的快速的sort方法。
对字典的键排序
- 根据键将值排序:
def sortedDictValues1(adict): keys = adict.keys() keys.sort() return [adict[key] for key in keys]----------def sortedDictValues2(adict): keys = adict.keys() keys.sort() return map(adict.get,keys)
不区分大小写对字符串列表排序
- 采用DSU方式:先创建一个辅助列表,每个元素都是元组,元组的元素则来自原列表,并当做“键”处理。
def case_insenseitive_sort1(string_list): alist = [(x.lower(),x) for x in string_list] alist.sort() return [x[1] for x in alist]#不改变原列表----------def case_insenseitive_sort2(string_list): alist = [(x.lower(),x) for x in string_list] alist.sort() string_list[:] = [x[1] for x in alist]#直接作用于原列表,改变原列表
- 更快捷的方式:
def case_insensitive_sort(string_list):#适用于普通字符串和unicode对象 return sorted(string_list,key=lambda s:s.lower())
根据对应值将键或索引排序
- 柱状图,实际上就是基于各种不同元素出现的次数,根据对应值将键或索引排序。下面是dict的一个子类,它为了这种应用加入了两个方法:
class hist(dict): def add(self,item,increment=1): '''为item的条目增加计数''' self[item] = 1 + self.get(item,0) def counts(self,reverse=False): '''返回根据对应值排序的键的列表''' aux = [(self[k],k) for k in self] aux.sort() if reverse: aux.reverse() return [k for v,k in aux]----------#跑个小例子:if __name__ == '__main__': sentence = 'hello world hello python' words = sentence.split() c = hist() for word in words: c.add(word) print 'ascending count:' print c.counts() print 'decending count:' print c.counts(reverse=True)#输出:ascending count:[(1, 'python'), (1, 'world'), (2, 'hello')]decending count:[(2, 'hello'), (1, 'world'), (1, 'python')]
- 如果想将元素的统计结果放到一个列表中,做法也非常类似:
class hist(list): def __init__(self,n): '''初始化列表,统计n个不同项的出现''' list.__init__(self,n*[0]) def add(self,item,increment=1): '''为item的条目增加计数''' self[item] += increment def counts(self,reverse=False): '''返回根据对应值排序的键的列表''' aux = [(v,k) for k,v in enumerate(self)] aux.sort() if reverse: aux.reverse() return [k for v,k in aux]
- 更简单快速的方法:
def sorted_keys(the_dict,keys,reverse): return sorted(keys,key=the_dict.__getitem__,reverse=reverse)
根据内嵌的数字将字符排序
- 首先将字符串按照数字与非数字切割开,然后将序列中的str型数字转化为int型数字,最后将其放在元组作为排序的键。例如下面这个字符串列表进行排序:
files = ['weibo9.txt','weibo6.txt','weibo2.txt','weibo8.txt']
按照上述思路:
import redef find_numbers(elem): re_digits = re.compile(r'(\d+)') pieces = re_digits.split(elem) pieces[1] = int(pieces[1]) return pieces[1]----------def sort_by_find_numbers1(the_list): aux = [(find_numbers(i),i) for i in the_list] aux.sort() return [j for i,j in aux]files = ['weibo9.txt','weibo6.txt','weibo2.txt','weibo8.txt']print ' '.join(sort_by_find_numbers1(files))#更美观的输出print sort_by_find_numbers1(files)#输出为列表#输出:weibo2.txt weibo6.txt weibo8.txt weibo9.txt['weibo2.txt', 'weibo6.txt', 'weibo8.txt', 'weibo9.txt']
- 更快捷的操作(使用上面定义的find_numbers函数):
def sort_by_find_numbers2(the_list): return sorted(the_list,key=find_numbers)
以随机顺序处理列表的元素
- 最简单和最高效的方法:首先对序列洗牌,然后线性访问洗完牌的序列:
import random def process_all_in_random(data,process): data = list(data) random.shuffle(data) for elem in data: process(elem)
- 假如要从列表中随机挑选出一个元素,进行相应的处理后,将该元素删除。
import randomdef process_random_and_moveing(data,process): while data: elem = random.choice(data) a = process(elem) print a data.remove(elem)if __name__ == '__main__': d = ['1','2','3','4','5','5','5'] process_random_and_moving(d,int)##输出:2515345
- process_random_and_moving函数运行效率不高,因为每个data.remove都会线性地搜索整个列表以获取要删除的元素。
在添加元素时保持序列顺序
某序列需要在不断加入新元素后,扔处于排序完毕状态,以便检查或者删除当前序列中最小的元素。
- 首先会想到,可以调用
the_list.sort()
排序,然后用the_list.pop(0)
来获取和删除最小的元素。 - 引入堆的组织数据的结构。这是一种简洁的二叉树,能确保父节点总是比子节点小。在Python中维护一个堆的最好方式是使用列表,这个列表无需完成排序,却能够保证得到当前最小的元素,然后所有节点会被调整,以确保堆特性仍然有效:
the_list = [4,1,7,5,2,9,0]import heapqheapq.heapify(the_list)heapq.heappop(the_list)#返回并删除最小元素heapq.heapreplace(the_list,10)#加入一个新元素后,返回并删除之前最小的元素
获取序列中最小的几个元素
- 可以先将序列排序,再使用sep[:n]获取最小的n个元素。
- 或者使用简单可行的生成器:
import heapqdef sort_(data): data = list(data) heapq.heapify(data) while data: yield heapq.heappop(data)
- 还有更快捷的方法:
import heapqdef n_smallest(n,data):#n个最小 return heapq.nsmallest(n,data)----------def n_largest(n,data):#n个最大 return heapq.nlargest(n,data)----------#也可不通过函数heapq.heapify(data)heapq.nsmallest(n,data)heapq.nlargest(n,data)
0 0
- Python Cookbook 2 ——搜索和排序
- Python Cookbook 2——Python技巧
- SQL Cookbook—查询、排序
- Python 小技巧——<Cookbook>读书笔记(2)deque和heapq
- Python GUI Cookbook —— 布局管理
- Python GUI Cookbook —— 定制 widgets
- python字符串的操作——python cookbook
- python学习13-搜索和排序
- data imputation —— Python Data Science Cookbook
- sampling brief —— python data science cookbook
- Removing stop words —— Python Data Science CookBook
- Python CookBook笔记——数据结构与算法
- Python Cookbook
- python CookBook
- Python-cookbook
- python cookbook:第一章 数据结构和算法
- python技巧(2):--python cookbook学习笔记
- OpenSSL Cookbook 2——私钥
- Error: java.lang.RuntimeException: Some file crunching failed, see logs for details
- Jquery实现拖拽可编辑模块
- c++链接mysql(vs2015)
- 蓝桥杯-入门训练-Fibonacci数列
- 【qt】在ubuntu下的安装教程
- Python Cookbook 2 ——搜索和排序
- GridView里面怎么限制文本的长度
- 设计一个可扩展的用户登录系统 (2)
- 并查集(以hdu1232 畅通工程为例)
- 使用RecyclerView自定义目录快速索引
- 蓝桥杯-入门训练-圆的面积
- 网站高并发的处理措施
- XX-Net使用:XX-Net在各平台使用方法介绍(一)
- HDU-1010(DFS)