python3 数据结构_Python3 CookBook学习笔记 -- 数据结构与算法

1. 迭代对象解压赋值

解压赋值操作可以应用到任何迭代对象上,如:列表、元组、字符串、文件对象、迭代器、生成器。

唯一的要求:

变量的数量必须跟序列元素的数量是一样的。

>>> p=(1,2,3,4)

>>> a,b,c,d=p

>>> a

1

>>> b

2

>>> c

3

>>> d

4

>>> datas=['apple', 'cherry', 1, (1,2,3,4)]

>>> a,b,c,d=datas

>>> a

'apple'

>>> b

'cherry'

>>> c

1

>>> d

(1, 2, 3, 4)

>>> s='faris'

>>> a,b,c,d,e=s

>>> a

'f'

>>> b

'a'

>>> c

'r'

>>> d

'i'

>>> e

's'

2. 扩展迭代对象解压赋值

如果遇到不确定个数或任意个数元素的可迭代对象时,则需要使用星号表达式可以用来解决这个问题。

假设你现在有一些用户的记录列表,每条记录包含一个名字、邮件,接着就是不确定数量的电话号码。

>>> record = ('Dave', 'dave@example.com', '773-555-1212', '847-555-1212')

>>> name, email, *phone_numbers = record

>>> name

'Dave'

>>> email

'dave@example.com'

>>> phone_numbers

['773-555-1212', '847-555-1212']

>>>

如果你想解压一些元素后丢弃它们,你不能简单就使用 * , 但是你可以使用一个普通的废弃名称,比如 _ 或者 ign (ignore)。

>>> record = ('ACME', 50, 123.45, (12, 18, 2012))

>>> name, *_, (*_, year) = record

>>>

>>>

>>>

>>> name

'ACME'

>>> _

[12, 18]

>>>

>>>

>>> year

2012

3. 查找最大或最小的 N 个元素

heapq 模块有两个函数:nlargest() 和 nsmallest() 可以完美解决这个问题。

输出最大和最小的三个值:

>>> import heapq

>>> nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]

>>> print(heapq.nlargest(3, nums))

[42, 37, 23]

>>> print(heapq.nsmallest(3, nums))

[-4, 1, 2]

两个函数都能接受一个关键字参数,用于更复杂的数据结构中:

>>> 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'])

>>> expensive = heapq.nlargest(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}]

>>>

>>> expensive

[{'name': 'AAPL', 'shares': 50, 'price': 543.22}, {'name': 'ACME', 'shares': 75, 'price': 115.65}, {'name': 'IBM', 'shares': 100, 'price': 91.1}]

注意点

当要查找的元素个数相对比较小的时候,函数 nlargest() 和 nsmallest() 是很合适的。

如果你仅仅想查找唯一的最小或最大(N=1)的元素的话,那么使用 min() 和 max() 函数会更快些。

如果 N 的大小和集合大小接近的时候,通常先排序这个集合然后再使用切片操作会更快点 ( sorted(items)[:N] 或者是 sorted(items)[-N:] )。

4. 实现一个优先级队列

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]

class Item:

def __init__(self, name):

self.name = name

def __repr__(self):

return 'Item({!r})'.format(self.name)

q = PriorityQueue()

q.push(Item('foo'), 1)

q.push(Item('bar'), 5)

q.push(Item('spam'), 4)

q.push(Item('grok'), 1)

q.pop()

q.pop()

q.pop()

q.pop()

在上面代码中,队列包含了一个 (-priority, index, item) 的元组。 优先级为负数的目的是使得元素按照优先级从高到低排序。 这个跟普通的按优先级从低到高排序的堆排序恰巧相反。

对于Item对象是不支持相互比较的:

>>> a=Item('foo')

>>> b=Item('boo')

>>> a > b

Traceback (most recent call last):

File "test.py", line 26, in

a > b

TypeError: '>' not supported between instances of 'Item' and 'Item'

但是使用元组,则可以进行比较:

>>> class Item:

... def __init__(self, name):

... self.name = name

... def __repr__(self):

... return 'Item({!r})'.format(self.name)

...

>>>

>>> a=(1, Item('foo'))

>>> b=(2, Item('boo'))

>>> print (a > b)

False

5. 字典中的键映射多个值 multidict

一个字典就是一个键对应一个单值的映射。如果你想要一个键映射多个值,那么你就需要将这多个值放到另外的容器中, 比如列表或者集合里面。

d = {

'a' : [1, 2, 3],

'b' : [4, 5]

}

e = {

'a' : {1, 2, 3},

'b' : {4, 5}

}

使用 collections 模块中的 defaultdict 来构造一键多值的字典:

>>> from collections import defaultdict

>>>

>>> 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)

>>>

>>> d

defaultdict(, {'a': {1, 2}, 'b': {4}})

defaultdict 会自动为将要访问的键(就算目前字典中并不存在这样的键)创建映射实体。

>>> d = defaultdict(set)

>>>

>>>

>>> d['d']

set()

>>> d

defaultdict(, {'d': set()})

可以通过一个普通的字典上使用 setdefault() 去除这个情况:

>>> d = {}

>>> d.setdefault('a', []).append(1)

>>> d.setdefault('a', []).append(2)

>>> d.setdefault('b', []).append(4)

>>>

>>> d

{'a': [1, 2], 'b': [4]}

>>> d['c']

Traceback (most recent call last):

File "", line 1, in

KeyError: 'c'

>>>

>>> d['a']

[1, 2]

这种写法是让人非常别扭的,因为需要多些一次[]。

也可以自己实现:

d = {}

for key, value in pairs:

if key not in d:

d[key] = []

d[key].append(value)

但是从Python提倡的简洁上来说,没有defaultdict简洁:

d = defaultdict(list)

for key, value in pairs:

d[key].append(value)

6. 字典按顺序输出

为了能控制一个字典中元素的顺序,你可以使用 collections 模块中的 OrderedDict 类

>>> from collections import OrderedDict

>>>

>>> d = OrderedDict()

>>> d['foo'] = 1

>>> d['bar'] = 2

>>> d['spam'] = 3

>>> d['grok'] = 4

>>>

>>> d

OrderedDict([('foo', 1), ('bar', 2), ('spam', 3), ('grok', 4)])

>>>

>>> for key in d:

... print(key, d[key])

...

foo 1

bar 2

spam 3

grok 4

OrderedDict 内部维护着一个根据键插入顺序排序的双向链表。每次当一个新的元素插入进来的时候, 它会被放到链表的尾部。

一个 OrderedDict 的大小是一个普通字典的两倍,因为它内部维护着另外一个链表。 大量数据时,需要权衡效率。

7. 字典运算

如何在数据字典中 执行 求最小值、最大值、排序?

上面我们学习的方法为:

使用heapq 中的 nlargest、nsmallest、heapify完成堆排序。

使用 sorted函数。

使用 min函数 和 max函数

参考股票名和价格映射字典:

prices = {

'ACME': 45.23,

'AAPL': 612.78,

'IBM': 205.55,

'HPQ': 37.20,

'FB': 10.75

}

7.1 heapq

显然无法实现字典排序,无论是根据key排序,还是根据value排序。

>>> heapq.nlargest(1, prices)

['IBM']

>>> heapq.nsmallest(1, prices)

['AAPL']

>>> heapq.heapify(prices)

Traceback (most recent call last):

File "", line 1, in

TypeError: heap argument must be a list

7.2 sorted

显然 sorted无法实现对value的排序,只能对key进行排序并返回排好序的key列表,且还需要再次遍历这个列表才能获取value。

>>> sorted(prices)

['AAPL', 'ACME', 'FB', 'HPQ', 'IBM']

7.2 min max

显然和sorted是相同的问题,只能对key进行排序。

>>> min(prices)

'AAPL'

>>>

>>>

>>> max(prices)

'IBM'

方案1 zip:

我们为了对值进行操作时,需要使用zip() 函数对key与value进行翻转。

>>> list(zip(prices.values(), prices.keys()))<

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构与算法(Python) 一、引入概念 1-01算法引入 1-02 时间复杂度与大O表示法 1-03-最坏时间复杂度与计算规则 1-04-常见时间复杂度与大小关系 1-05-代码执行时间测量模块 1-06-Python列表类型不同操作的时间效率 1-07-Python列表与字典操作的时间复杂度 1-08-数据结构引入 二、顺序表 2-01 内存、类型本质、连续存储 recv 2-02 基本顺序表与元素外围顺序表 recv 2-03 顺序表的一体式结构与分离式结构 recv 2-04 顺序表数据区替换与扩充 recv 三、栈 3-01 栈与队列的概念 3-02 栈的实现 3-03 队列与双端队列的实现 四、链表 4-01 链表的提出 4-02 单链表的ADT模型 4-03 Python中变量标识的本质 4-04 单链表及结点的定义代码 4-05 单链表的判空、长度、遍历与尾部添加结点的代码实现 4-06 单链表尾部添加和在指定位置添加 4-07 单链表查找和删除元素 4-08 单链表与顺序表的对比 4-09 单向循环链表遍历和求长度 4-10 单向循环链表添加元素 4-11 单向循环链表删除元素 4-12 单向循环链表删除元素复习及链表扩展 4-13 双向链表及添加元素 4-14 双向链表删除元素 五、排序与搜索 5-01 排序算法的稳定性 5-02 冒泡排序及实现 5-03 选择排序算法及实现 5-04 插入算法 5-05 插入排序 5-06 插入排序2 5-07 希尔排序 5-08 希尔排序实现 5-09 快速排序 5-10 快速排序实现1 (1) 5-10 快速排序实现1 5-11 快速排序实现2 5-12 归并排序 5-13 归并排序 代码执行流程 5-14 归并排序时间复杂度及排序算法复杂度对比 5-15 二分查找 5-16 二分查找时间复杂度 六、树和树的算法 6-01 树的概念 6-02 二叉树的概念 6-03 二叉树的广度优先遍历 6-04 二叉树的实现 6-05 二叉树的先序、中序、后序遍历 6-06 二叉树由遍历确定一棵树 ———————————————— 版权声明:本文为CSDN博主「dwf1354046363」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/dwf1354046363/article/details/119832814

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值