《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编码. -增加示例:单元格编辑->杂项-> ...
随机推荐
- Flex中利用事件机制进行主程序与子窗体间参数传递
在开发具有子窗体,或者itemrenderer的应用时,常常涉及到子窗体向父窗体传递参数或者从itemrenderer内的控件向外部的主程序传递参数的需求.这些都可以通过事件机制这一统一方法加以解决. ...
- layui table 表格上添加日期控件
方法一: var tableInit = table.render({ elem: '#tbtxrz' , method: 'post' , data: jsonData , height: &quo ...
- API安全综述
API安全综述 译自:An Overview on API Security. 本文概括了API防护有关的方方面面,从上层视角介绍了API防护中主要注意的点,并给出了相应的建议.本文可以作为一个API ...
- jdk keytool 自签证书
jdk keytool 自签证书 https需要用到ssl证书,可以从阿里等平台申请,本文采用jdk keytool进行自签证书. 生成环境:linux 用jdk自带keytool工具生成密钥库 ke ...
- bcprov-jdk15-145.rar
javapdf文件操作,加密包 bcprov-jdk15-145.rar https://files.cnblogs.com/files/blogs/692137/bcprov-jdk15-145.r ...
- mysql 的基础操作
1.建表 create table 表名( 字段一 数据类型 [列属性] , 字段二 数据类型 [列属性], ......... )[表类型][表字符集][注释]; 注意:MySQL命令终止符为分号 ...
- IDA 动态调试
感谢南邮,让我把ida动态调试,给搞定了,困扰了很久,之前下的ubuntu的源,好像有问题,ifconfig这个命令一直装不上,突然想起来了我的服务器很久没用了,重装了下系统,换成ubuntu,这里记 ...
- WPF教程十:如何使用Style和Behavior在WPF中规范视觉样式
在使用WPF编写客户端代码时,我们会在VM下解耦业务逻辑,而剩下与功能无关的内容比如动画.视觉效果,布局切换等等在数量和复杂性上都超过了业务代码.而如何更好的简化这些编码,WPF设计人员使用了Styl ...
- SpringBoot | 2.1 SpringBoot自动装配原理
@ 目录 前言 1. 引入配置文件与配置绑定 @ImportResource @ConfigurationProperties 1.1 @ConfigurationProperties + @Enab ...
- Java的代理模式
最近在学习Spring,关于Spring AOP的代理模式不是很了解,看了一篇博文就懂了. https://www.cnblogs.com/cenyu/p/6289209.html Java的三种代理 ...