《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编码. -增加示例:单元格编辑->杂项-> ...
随机推荐
- SpringBoot | 1.2 全注解下的Spring IoC
前言 在学习SpringBoot之前,有几个Spring的重要的基础概念需要提一下,SpringBoot对这些基础概念做进一步的封装,完成自动配置.首先就是Spring的控制反转IOC,由于Sprin ...
- com.rabbitmq.client.impl.Frame.readFrom(Frame.java:95)
RabbitMQ 基于Erlang 实现, 客户端可以用Python | Java | Ruby | PHP | C# | Javascript | Go等语言来实现.这里做个java语言的测试.首先 ...
- Shell常用工具find,grep,sed,awk,xargs命令
最近学习shell命令,对grep,sed,awk命令有点混乱,故小结一下,巩固一遍. 注意:find , grep , sed, awk可使用基本正则表达式字符,find,grep,awk也支持扩展 ...
- git使用---安装,提交,回退,修改,分支,标签等
下面是对git的各种使用及命令的基础使用,来自廖雪峰老师的git教程,这个收录下,作为git的使用总结. github上面地址为:https://github.com/Zhangguoliu/lear ...
- Redis的结构和运作机制
目录 1.数据库的结构 1.1 字典的底层实现 2.过期键的检查和清除 2.1 定时删除 2.2 惰性删除 2.3 定期删除 2.4 对RDB.AOF和复制的影响 3.持久化机制 3.1 RDB方式 ...
- F5 Http monitor
The BIG-IP HTTP health monitor attempts to mabtch the configured Receive String against the HTTP res ...
- JS请求节流
少废话,撸代码.欧耶! 1.节流器 // 对函数进行 节流 function throttle (fn, interval = 500) { let timer = null; let firstTi ...
- 简单DOS命令
1.nslookup命令 nslookup命令是用来解析域名的,举个例子:我们只知道百度的域名是www.baidu.com 想要知道它的ip的话就要使用nslookup命令了nslookup www. ...
- ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: NO)解决办法
问题:ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO) 很久没用这台电脑的mysql ...
- [刘阳Java]_CSS图片画廊
图片画廊也是一种比较经典的案例.本节文章主要简单给大家介绍了CSS2实现图片画廊,采取的实现思路 ul放置图片 li标签里面嵌套a标签 a标签里面嵌套两个图片的标签 通过简单的伪类来实现图片预览效果 ...