您的位置:首页 > 理论基础 > 数据结构算法

Python3 cookbook学习笔记-数据结构与算法1

2017-03-17 11:47 295 查看
最近在自学python,在大概学习了最基础的语法之后,不知该如何继续,突然发现这本书还不错,读之,记之。

1.1 解压序列赋值给多个变量

1.2 解压可迭代对象赋值给多个变量

1.3 保留最后N个元素

1.4 查找最大或最小的N个元素

1.5 实现一个优先级队列

1.6 字典中的键值映射多个值

1.7 字典排序

1.8 字典的运算

1.9 查找两字典的相同点

1.10 删除序列相同的元素并保持顺序

1.11 命名切片

1.12 序列中出现次数最多的元素

1.13 通过某个关键字排序一个字典列表

1.14 排序不支持原生比较的对象

1.15 通过某个字段将记录分组

1.16 过滤序列元素

1.17 从字典中提取子集

1.18 映射名称到序列元素

1.19 转换并同时计算数据

1.20 合并多个字典或映射

解压序列赋值给多个变量

将一个元组(tuple)中的数据赋值给多个变量:

>>> t = (4,5)
>>> x, y = t
>>> x
4
>>> y
5


将一个列表(tuple)中的数据赋值给多个变量:

>>> L = ['fww', 33, 170, 72, (1983, 10, 25)]
>>> name, age, height, weight, birth = L
>>> name
'fww'
>>> age
33
>>> height
170
>>> weight
72
>>> birth
(1983, 10, 25)
>>>
>>> name, age, height, weight, (year, mon, day) = L
>>> year
1983
>>> mon
10
>>> day
25


如果变量个数和序列元素的个数不匹配,会产生一个异常:

>>> t = (1, 2, 3)
>>> a, b = t
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)
>>> a, b, c, d = t
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 4, got 3)
>>> a, b, c = t
>>> a
1
>>> b
2
>>> c
3


实际上,这种解压赋值可以用在任何可迭代对象上面,而不仅仅是列表或者元组。 包括 字符串,文件对象,迭代器和生成器。

>>> s = 'hello'
>>> a, b, c, d, e = s
>>> a
'h'
>>> b
'e'
>>> c
'l'
>>> d
'l'
>>> e
'o'


有时候,你可能只想解压一部分,丢弃其他的值。对于这种情况Python并没有提供特殊 的语法。 但是你可以使用任意变量名去占位,到时候丢掉这些变量就行了。

>>> s = 'world'
>>> _, b, c, _, _ = s
>>> b
'o'
>>> c
'r'


个人感悟:使用任意变量名去占位这种做法,感觉有点不太舒服。

解压可迭代对象赋值给多个变量

我们已经看到了,如果一个可迭代对象的元素个数超过变量个数时,会抛出一个异常。但是有时候,我们确实不像解压出所有元素,而只是其中的N个元素,怎么办呢?Python的星号表达式可以用来解决这个问题。

>>> record = ('fww', '123@qq.com','12345678911', '010-88888888')
>>> name, email, *phone_numbers = record
>>> name
'fww'
>>> email
'123@qq.com'
>>> phone_numbers
['12345678911', '010-88888888']


去掉一个最高分,去掉一个最低分,求其他得分的平均值:

def drop_first_last(grades):
first, *middle, last = grades
return avg(middle)


星号表达式也能用在列表的开始部分:

>>> *trailing, current = [10, 8, 7, 1, 9, 5, 10, 3]
>>> trailing
[10, 8, 7, 1, 9, 5, 10]
>>> current
3


星号表达式在迭代元素为可变长元组的序列时是很有用的:

>>> records = [
...     ('foo', 1, 2),
...     ('bar', 'hello'),
...     ('foo', 3, 4)
... ]
>>> print(records)
[('foo', 1, 2), ('bar', 'hello'), ('foo', 3, 4)]
>>> for tag, *args in records:
...     if tag == 'foo':
...         print(*args)
...     elif tag == 'bar':
...         print(*args)
...
1 2
hello
3 4


星号解压语法在字符串操作的时候也会很有用,比如字符串的分割:

>>> line = 'nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false'
>>> uname, *fields, homedir, sh = line.split(':')
>>> uname
'nobody'
>>> homedir
'/var/empty'
>>> sh
'/usr/bin/false'


保留最后N个元素

保留有限历史记录正是collections.deque 大显身手的时候,先看看简单的deque 的例子:

>>> from collections import deque
>>> q = deque(maxlen=3)
>>> q.append(1)
>>> q.append(2)
>>> q.append(3)
>>> q
deque([1, 2, 3], maxlen=3)
>>> q.append(4)
>>> q
deque([2, 3, 4], maxlen=3)
>>> q.append(5)
>>> q
deque([3, 4, 5], maxlen=3)


更一般的, deque类可以被用在任何你只需要一个简单队列数据结构的场合。 如果你不 设置最大队列大小,那么就会得到一个无限大小队列,你可以在队列的两端执行添加和弹 出元素的操作。

>>> q = deque()
>>> q.append(1)
>>> q.append(2)
>>> q.append(3)
>>> q
deque([1, 2, 3])
>>> q.appendleft(4)
>>> q
deque([4, 1, 2, 3])
>>> q.pop()
3
>>> q
deque([4, 1, 2])
>>> q.popleft()
4
>>> q
deque([1, 2])


当然你也可以使用列表实现这些操作,但是在队列两端插入或删除元素时间复杂度都是o(1) ,而在列表的开头插入或删除元素的时间复杂度为o(n)。

最后再来看保留最后N个元素的问题:

def search(lines, pattern, history=5):
previous_lines = deque(maxlen=history)
for li in lines:
if pattern in li:
yield li, previous_lines
previous_lines.append(li)


个人感悟:这个例子我没有实际测试,因为初学,对yield的理解还不到位。但基本思路应当是这样:把所有满足条件的记录不断往队列中加,迭代完成后,最后队列中的数据就是最后5个元素。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息