《Python CookBook》读书笔记-数据结构和算法(一)

1. 把一个序列L拆分为包含n(n<=len(l))个单独的变量

用法

data = ['ACME', 50, 90, (2017, 3, 8)]
name, shares, price, date = data
print(name, date)
name, _, _, (year, *_) = data    # 只取某几个元素而忽略其他元素
print(name, year)
ACME (2017, 3, 8)
ACME 2017

说明

做分解操作,有时可能需要丢弃某些值,通常可以选一个一般用不到的变量名来表示这些要被丢弃的元素,如可以用 '_','_', 'ign(ignored)', 'ign'。对于分解未知或者任意长度的可迭代对象时,使用这种*式的语法特别有用。

例子

# 计算平均分时一般要去掉最高和最低分
def drop_first_last(grades):
    first, *middle, last = grades
    return avg(middle)
# 实现递归
def sum(items):
    head, *tail = items
    return head + sum(tail) if tail else head

2. 通过heapq模块来找最大或最小的N个元素

用法

import heapq
import random

nums = random.sample(range(-20, 50), 10) # 从range(-20, 50)中随机取出10个元素
print(nums)
print(heapq.nlargest(3, nums))
print(heapq.nsmallest(3, nums))

dict_nums = [dict.fromkeys('a', i) for i in nums]
print(dict_nums)
print(heapq.nlargest(3, dict_nums, key=lambda s: s['a'])) # 通过接受参数key,可以在更复杂的数据结构上进行操作
print(heapq.nsmallest(3, dict_nums, key=lambda s: s['a']))

heap = list(nums)
heapq.heapify(heap) # 把nums以堆的顺序进行排列
print(heap)
print(heapq.heappop(heap)) # heap[0]总是最小那个元素,heappop取出最小的元素,取出最小元素后会重新构造堆
print(heapq.heappop(heap))
[-1, 43, 16, 47, 31, -11, 4, 49, 13, 28]
[49, 47, 43]
[-11, -1, 4]
[{'a': -1}, {'a': 43}, {'a': 16}, {'a': 47}, {'a': 31}, {'a': -11}, {'a': 4}, {'a': 49}, {'a': 13}, {'a': 28}]
[{'a': 49}, {'a': 47}, {'a': 43}]
[{'a': -11}, {'a': -1}, {'a': 4}]
[-11, 13, -1, 43, 28, 16, 4, 49, 47, 31]
-11
-1

说明

  • 堆最重要的特性是heap[0]总是最小那个元素
  • 当要找的元素数量相对较小时,适用nlargest()和nsmallest(),注意nlargest()和nsmallest()的实际实现会根据适用他们的不同方式而有所不同,如N仅仅集合大小时会先排序
  • 如果只是简单的找到最小或最大的元素,则用min()和max()合适
  • 如果N和集合本身大小差不多,通常更快的方法是先对集合排序,然后做切片操作

3. 实现优先级队列

问题

实现一个队列,它能以给定的优先级来对元素进行排序,每次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]
    
pq = PriorityQueue()
pq.push('jlan', 5)
pq.push('hua', 2)
pq.push('lann', 4)
pq.push('bob', 1)
pq.push('han', 3)
print(pq._queue)
print(pq.pop())
print(pq._queue)
print(pq.pop())
[(-5, 0, 'jlan'), (-3, 4, 'han'), (-4, 2, 'lann'), (-1, 3, 'bob'), (-2, 1, 'hua')]
jlan
[(-4, 2, 'lann'), (-3, 4, 'han'), (-2, 1, 'hua'), (-1, 3, 'bob')]
lann

说明(详解见P10)

  1. 这个方案的核心在于heapq模块的使用。heappush()和heappop()分别从_queue中插入和移除,且保证列表中第一个元素的优先级最低。heappop()总是返回‘最小’元素,因此这是队列能弹出正确元素的关键。
  2. 在这段代码中,队列以元组(-priority, index, item)的形式组成,priority取负值是为了让队列能够按优先级从高到底排序(正常情况下,堆是按从小到大排序的),构造堆时按-priority排序,当priority相同时按index排序。
  3. 变量index的作用是为了将具有相同优先级的元素以适当的顺序排列(以入队顺序)。

字典操作

  • 将键映射到多个值上
from collections import defaultdict

d = defaultdict(list)
d['a'].append(1)
d['a'].append(2)
print(d)
defaultdict(<class 'list'>, {'a': [1, 2]})
  • 有序字典
    使用collections.OrderedDict可以保持字典有序,OrderedDict内部维护了一个双向链表,会根据元素加入的顺序来排列键的位置。OrderedDict的大小是普通字典的2倍多。

  • 在字典上进行求最大值,最小值等操作

prices = {
    'apple': 2,
    'banada': 3,
    'orange': 1,
    'peach': 4
}

# 在字典上执行常见的操作,只会处理键,而不是值
min(prices) # 返回'apple'
max(prices) # 返回'peach'

# 可以用dict.values()来处理值
min(prices.values()) # 返回 1
max(prices.values()) # 返回 4

min(prices, key=lambda x: prices[x]) # 返回'orange'
max(prices, key=lambda x: prices[x]) # 返回'peach'

# 对字典进行求最大值,最小值等操作一般用下边的方法
min(zip(prices.values(), prices.keys())) # 返回(1, 'orange')
max(zip(prices.values(), prices.keys())) # 返回(4, 'orange')
# zip()创建了一个迭代器,其内容只能被消费一次
# 涉及(value, key)对的比较时,如果多个条目有相同的value,此时将根据key进行判定
(4, 'peach')
  • 在字典中寻找相同点
# 找出两个字典可能相同的地方(相同的键或者值)
a = {'x': 1, 'y': 2, 'z': 3}
b = {'w': 11, 'y': 2, 'z': 13}

# a和b相同的键
a.keys() & b.keys() # 返回 {'y', 'z'}

# 在a中但是不在b中的键
a.keys() - b.keys() # 返回 {'x'}

# a和b中相同的{key: value}
a.items() & b.items() # 返回 {('y', 2)}
{('y', 2)}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,254评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,875评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,682评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,896评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,015评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,152评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,208评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,962评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,388评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,700评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,867评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,551评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,186评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,901评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,689评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,757评论 2 351

推荐阅读更多精彩内容

  • 1 序 2016年6月25日夜,帝都,天下着大雨,拖着行李箱和同学在校门口照了最后一张合照,搬离寝室打车去了提前租...
    RichardJieChen阅读 5,085评论 0 12
  • 数据结构和算法 通过*表达式或者是一个用不到的变量来拆分,处理序列 使用 _ 符号舍弃序列中不需要的值 使用 * ...
    buildbody_coder阅读 256评论 0 0
  • 本文涉及更多的是概念,代码部分请参考之前写过的 2 篇博客 基于Javascript的排序算法基本数据结构和查找算...
    faremax阅读 1,235评论 0 2
  • 课程介绍 先修课:概率统计,程序设计实习,集合论与图论 后续课:算法分析与设计,编译原理,操作系统,数据库概论,人...
    ShellyWhen阅读 2,272评论 0 3
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,644评论 18 139