《Python Cookbook v3.0.0》Chapter1 数据结构和算法
感谢:
https://github.com/yidao620c/python3-cookbook
如有侵权,请联系我整改。
本文章节会严格按照原书(以便和原书对照,章节标题可能会略有修改),内容会有增删。
1.1 解引、解引赋值
1.1.1 解引
通过*
可以解引(书中翻译为解压,还是解引更舒服些),
示例,
>>> (4,5)
(4, 5)
>>> print(*(4,5))
4 5
>>> str='akdfjasl'
>>> str
'akdfjasl'
>>> print(*str)
a k d f j a s l
>>> d={'a':1,'b':2}
>>> d
{'a': 1, 'b': 2}
>>> print(*d)
a b
1.1.2 解引赋值
可以用占位符,丢弃不要的数据。
示例,
>>> data = [ 'ACME', 50, 91.1, (2012, 12, 21) ]
>>> _, shares, price, _ = data
>>> shares
50
>>> price
91.1
>>>
通过*
可以赋值多个变量,
实例,
>>> *trailing, current = [10, 8, 7, 1, 9, 5, 10, 3]
>>> trailing
[10, 8, 7, 1, 9, 5, 10]
>>> current
3
1.3 只保留N个元素
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)
1.4 最大/最小的N个元素
import heapq
示例,
>>> portfolio = [
{'name': 'IBM', 'shares': 100, 'price': 91.1},
{'name': 'AAPL', 'shares': 50, 'price': 543.22},
{'name': 'FB', 'shares': 200, 'price': 21.09},
{'name': 'HPQ', 'shares': 35, 'price': 31.75},
{'name': 'YHOO', 'shares': 45, 'price': 16.35},
{'name': 'ACME', 'shares': 75, 'price': 115.65}
]
>>> cheap = heapq.nsmallest(3, portfolio, key=lambda s: s['price'])
>>> cheap
[{'name': 'YHOO', 'shares': 45, 'price': 16.35}, {'name': 'FB', 'shares': 200, 'price': 21.09}, {'name': 'HPQ', 'shares': 35, 'price': 31.75}]
堆数据结构最重要的特征是 heap[0] 永远是最小的元素。并且剩余的元素可以很
容易的通过调用 heapq.heappop() 方法得到,该方法会先将第一个元素弹出来,然后
用下一个最小的元素来取代被弹出元素(这种操作时间复杂度仅仅是 O(log N))
示例,
>>> nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
>>> import heapq
>>> heap = list(nums)
>>> heapq.heapify(heap)
>>> heap
[-4, 2, 1, 23, 7, 2, 18, 23, 42, 37, 8]
>>> heapq.heappop(heap)
-4
>>> heapq.heappop(heap)
1
>>> heapq.heappop(heap)
2
1.5 优先级队列
怎样实现一个按优先级排序的队列?并且在这个队列上面每次 pop 操作总是返回
优先级最高的那个元素
import heapq
class PriorityQueue:
def __init__(self):
self._queue = []
self._index = 0
def push(self, item, priority):
heapq.heappush(self._queue, (-priority, self._index, item))
self._index += 1
def pop(self):
return heapq.heappop(self._queue)[-1]
注意这个index,作用是当
item
本身不支持比较的时候,在priority
相同时,可以通过index
比较,即,按照插入顺序排序
1.6 multidict(多值字典)
from collections import defaultdict
比如,
d = {
'a' : [1, 2, 3],
'b' : [4, 5]
}
e = {
'a' : {1, 2, 3},
'b' : {4, 5}
}
值可用list、set等存储
d = defaultdict(list)
d['a'].append(1)
d['a'].append(2)
d['b'].append(4)
d = defaultdict(set)
d['a'].add(1)
d['a'].add(2)
d['b'].add(4)
用
defaultdict
维护非常便利
1.7 OrderedDict(顺序字典)
from collections import OrderedDict
如果想控制字典顺序,可以用
OrderedDict
[TODO]
1.8 字典运算
可以用zip
打包成元组,
prices = {
'ACME': 45.23,
'AAPL': 612.78,
'IBM': 205.55,
'HPQ': 37.20,
'FB': 10.75
}
min_price = min(zip(prices.values(), prices.keys()))
# min_price is (10.75, 'FB')
也可以用key
,
min(prices, key=lambda k: prices[k])
1.9 字典的异同
可以用
keys()
,items()
方法
a = {
'x' : 1,
'y' : 2,
'z' : 3
}
b = {
'w' : 10,
'x' : 11,
'y' : 2
}
# Find keys in common
a.keys() & b.keys() # { 'x', 'y' }
# Find keys in a that are not in b
a.keys() - b.keys() # { 'z' }
# Find (key,value) pairs in common
a.items() & b.items() # { ('y', 2) }
# Make a new dictionary with certain keys removed
c = {key:a[key] for key in a.keys() - {'z', 'w'}}
# c is {'x': 1, 'y': 2}
注意,字典的
values()
并不支持上述操作,原因是,值并不一定是相同的形式,
确切的讲,值中的元素个数可能是不同的;而键虽然形式也可能不同,但个数永远是1
1.10 删除相同元素,但保持原顺序
set
结合yield
def dedupe(items, key=None):
seen = set()
for item in items:
val = item if key is None else key(item)
if val not in seen:
yield item
seen.add(val)
加
key
方法的原因是,items
并不一定是hashable
的,比如dict
示例,
>>> a = [ {'x':1, 'y':2}, {'x':1, 'y':3}, {'x':1, 'y':2}, {'x':2, 'y':4}]
>>> list(dedupe(a, key=lambda d: (d['x'],d['y'])))
[{'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 2, 'y': 4}]
>>> list(dedupe(a, key=lambda d: d['x']))
[{'x': 1, 'y': 2}, {'x': 2, 'y': 4}]
注意,使用
set()
构造,或者使用set.add()
都会改变顺序,后者还会排序
1.11 切片
>>> items = [0, 1, 2, 3, 4, 5, 6]
>>> a = slice(2, 4)
>>> items[a] = [10,11]
>>> del items[a]
1.12 次数最多的元素
from collections import Counter
示例,
word_counts = Counter(words)
top_three = word_counts.most_common(3)
# Outputs [('eyes', 8), ('the', 5), ('look', 4)]
其中
words
可以是list
、tupple
,当然set
也可以,不过没有意义
Counter()
返回的结果类似字典,形如,
Counter({'eyes':8,'the':5})
实际上,它的类型是<class 'collections.Counter'>
注意,虽然它看起来像字典,但某些操作和字典不同,比如,
update
,在dict
中,update意味着新值覆盖旧值,而在Counter
中,
update意味着新增计数,在原有基础上增加
>>> d
{'a': 1, 'b': 2}
>>> d2
{'a': 1, 'b': 3}
>>> d.update(d2)
>>> d
{'a': 1, 'b': 3}
>>> w=dict(d)
>>> w
{'a': 1, 'b': 3}
>>> cw=Counter(w)
>>> cw
Counter({'b': 3, 'a': 1})
>>> w2=dict(w)
>>> cw.update(w2)
>>> cw
Counter({'b': 6, 'a': 2})
同时,
Counter
的update
,入参也可以是另一个Counter
,
除了update
,Counter
还支持+
、-
运算
1.13 通过关键字给字典列表排序
from operator import itemgetter
示例,
rows_by_lfname = sorted(rows, key=itemgetter('lname','fname'))
itemgetter
的效率比lambda
高,结果是等价的
1.14 通过关键字给结构体列表排序
这里和1.13的区别是,上面是dict
,这里是class
,
from operator import attrgetter
示例,
by_name = sorted(users, key=attrgetter('last_name', 'first_name'))
不限于
sorted
,min
,max
都可以用,同itemgetter
一样,效率比lamdba
高,
至于,为何class
不能用itemgetter
,是因为key
必须是一个callable
对象,即,
可()
调用的,itemgetter
一个class
的属性,无法创建这样一个对象
1.15 通过某个字段分组
比如一堆记录,按日期进行分组。
from itertools import groupby
注意,
groupby
会按照顺序处理,所以在使用前,需要先进行排序
示例,
rows = [
{'address': '5412 N CLARK', 'date': '07/01/2012'},
{'address': '5148 N CLARK', 'date': '07/04/2012'},
{'address': '5800 E 58TH', 'date': '07/02/2012'},
{'address': '2122 N CLARK', 'date': '07/03/2012'},
{'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'},
{'address': '1060 W ADDISON', 'date': '07/02/2012'},
{'address': '4801 N BROADWAY', 'date': '07/01/2012'},
{'address': '1039 W GRANVILLE', 'date': '07/04/2012'},
]
rows.sort(key=itemgetter('date'))
for date, items in groupby(rows, key=itemgetter('date')):
print(date)
for i in items:
print(' ', i)
07/01/2012
{'date': '07/01/2012', 'address': '5412 N CLARK'}
{'date': '07/01/2012', 'address': '4801 N BROADWAY'}
07/02/2012
{'date': '07/02/2012', 'address': '5800 E 58TH'}
{'date': '07/02/2012', 'address': '5645 N RAVENSWOOD'}
{'date': '07/02/2012', 'address': '1060 W ADDISON'}
groupby
返回的是一个迭代器,内容类似一个tupple
1.16 列表推导
示例,
>>> mylist = [1, 4, -5, 10, -7, 2, 3, -1]
>>> import math
>>> [math.sqrt(n) for n in mylist if n > 0] //过滤,并计算
>>> clip_neg = [n if n > 0 else 0 for n in mylist] //值替代
>>> more5 = [n > 5 for n in counts] //返回true、false list
其中
过滤
,也可以用filter
实现
true、false list可以结合from itertools import compress
的compress
来压缩表项
1.17 字典推导
prices = {
'ACME': 45.23,
'HPQ': 37.20,
'FB': 10.75
}
p1 = {key: value for key, value in prices.items() if value > 200}
tech_names = {'AAPL', 'IBM', 'HPQ', 'MSFT'}
p2 = {key: value for key, value in prices.items() if key in tech_names}
推导,比
dict()
构造效率高
1.18 命名元组
from collections import namedtuple
不再通过
下标
访问,而是通过类似字典的方式访问
虽然是tupple
,但提供了_replace
方法来修改元素内容
示例,
Stock = namedtuple('Stock', ['name', 'shares', 'price', 'date', 'time'])
stock_prototype = Stock('', 0, 0.0, None, None)
# Function to convert a dictionary to a Stock
def dict_to_stock(s):
return stock_prototype._replace(**s)
>>> a = {'name': 'ACME', 'shares': 100, 'price': 123.45}
>>> dict_to_stock(a)
Stock(name='ACME', shares=100, price=123.45, date=None, time=None)
这里的字典解引很有意思,它等效于
stock_prototype._replace(name='acmd',shares=999)
1.19 聚集函数的推导
原文标题是,转换并同时计算数据。但看起来,形式类似推导。
聚集函数,sum
、min
、max
等。
示例,
s = sum(x * x for x in nums)
min_shares = min(s['shares'] for s in portfolio)
min
、max
中,效果等效使用key
1.20 合并多个字典或映射
前文有讲过普通字典dict
以及Counter
的update
,
这里是另一种形式,
from collections import ChainMap
从名字上,它就是chain
,链,将dict
链起来,
当多个
dict
有键值重复时,返回首个值
《Python Cookbook v3.0.0》Chapter1 数据结构和算法的更多相关文章
- 《Python Cookbook v3.0.0》Chapter2 字符串、文本
感谢: https://github.com/yidao620c/python3-cookbook 如有侵权,请联系我整改. 本文章节会严格按照原书(以便和原书对照,章节标题可能会略有修改),内容会有 ...
- 【python cookbook】【数据结构与算法】4.找到最大或最小的N个元素
问题:想在某个集合中找出最大或最小的N个元素 解决方案:heapq模块中的nlargest()和nsmallest()两个函数正是我们需要的. >>> import heapq &g ...
- 【python cookbook】【数据结构与算法】18.将名称映射到序列的元素中
问题:希望通过名称来访问元素,减少结构中对位置的依赖性 解决方案:使用命名元组collections.namedtuple().它是一个工厂方法,返回的是python中标准元组类型的子类,提供给它一个 ...
- 【python cookbook】【数据结构与算法】7.让字典保持有序
问题:创建一个字典,同时对字典做迭代或序列化操作时,也能控制其中元素的顺序: 解决方案:可以使用collections模块中的OrderedDict类来控制字典中元素的顺序.当对字典做迭代时,他会严格 ...
- 【python cookbook】【数据结构与算法】5.实现优先级队列
问题:要实现一个队列,它能够以给定的优先级对元素排序,且每次pop操作时都会返回优先级最高的那个元素: 解决方案:采用heapq模块实现一个简单的优先级队列 # example.py # # Exam ...
- 【推荐】.NETCore 简单且高级的库 csredis v3.0.0
前言 .NETCore 从1.0发布历经坎坷,一开始各种库缺失到现在的部分完善,走到今天实属不易. 比如 redis-cli SDK 简直是坑出不穷. 过去 .net 最有名望的 ServiceSta ...
- Centos 6.8 安装 Protocol Buffers , v3.2.0有 BUG ,安装 3.1.0
Centos 6.8 安装 Protocol Buffers , v3.2.0有 BUG ,安装 3.1.0 切换到用户目录 cd ~ 安装 python2.7,须加入zlib wget http ...
- 《数据结构与算法之美》 <03>数组:为什么很多编程语言中数组都从0开始编号?
提到数组,我想你肯定不陌生,甚至还会自信地说,它很简单啊. 是的,在每一种编程语言中,基本都会有数组这种数据类型.不过,它不仅仅是一种编程语言中的数据类型,还是一种最基础的数据结构.尽管数组看起来非常 ...
- FineUI(专业版)v3.2.0 发布(ASP.NET UI控件库)!
+2016-08-20 v3.2.0 +表格增强. +表格列RenderField增加属性ClientHtmlEncode,用于在客户端进行HTML编码. -增加示例:单元格编辑->杂项-> ...
随机推荐
- 使用 python 把一个文件生成 C 语言中的数组并保存到头文件中
(一)要做什么 之前有这么一个需求,是要把一个二进制文件里面的数据,转换成 C 代码里面的数组,可以看之前的一篇文章: NUC980 运行 RT-Thread 驱动 SPI 接口 OLED 播放 ba ...
- salesforce零基础学习(一百零五)Change Data Capture
本篇参考: https://developer.salesforce.com/docs/atlas.en-us.232.0.api_streaming.meta/api_streaming/using ...
- php-高级计算器
HTML代码: <!doctype html><html lang="en"><head> <meta charset="UTF ...
- c++中的继承关系
1 什么是继承 面向对象的继承关系指类之间的父子关系.用类图表示如下: 2 为什么要有继承?/ 继承的意义? 因为继承是面向对象中代码复用的一种手段.通过继承,可以获取父类的所有功能,也可以在子类中重 ...
- bash对一个目录中文件名的遍历
for var in * 对当前目录中文件名的遍历 for var in /xx/xx/* 对绝对路径目录的遍历 ${var##*/} 变量扩展取文件名的基名 $var =~ ^[0-9] ...
- 关于hive核心
一.DDL数据定义 1.创建数据库 1)创建一个数据库,数据库在 HDFS 上的默认存储路径是/user/hive/warehouse/*.db. hive (default)> create ...
- Mybatis order by 动态传参出现的一个小bug
大家好,我是老三,一个平平无奇的CRUD仔. 今天,我正在愉快地CRUD,突然发现出现一个Bug,我们来看看是怎么回事吧! 问题由来 一个简单的需求,要求把和当前用户相关的数据置顶展示. 这里,我用了 ...
- Mysql数据量较大时分页查询优化
据表 collect ( id, title ,info ,vtype) 就这4个字段,其中 title 用定长,info 用text, id 是主键,vtype是int,vtype是索引. 最后co ...
- 关于hashcode和equals方法说明
一.前言 我们都知道,要比较两个对象是否相等时需要调用对象的equals()方法,即判断对象引用所指向的对象地址是否相等,对象地址相等时,那么与对象相关的对象句柄.对象头.对象实例数据.对象类型数据等 ...
- 痞子衡嵌入式:i.MXRT1010, 1170型号上不一样的SNVS GPR寄存器读写控制设计
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1010, 1170型号上不一样的SNVS GPR寄存器读写控制设计. 痞子衡之前两篇文章 <在SBL项目实战中妙用i ...