python3高级教程 第一章数据结构和算法

第一章:数据结构和算法

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

在这里插入图片描述
在这里插入图片描述
如果变量个数和序列元素个数不匹配,会产生一个异常。
代码示例:

p = (4,5)
x, y, z = p
#会显示ValueError:need more than 2 values to uppack
#此时删掉z则error会消失

有条件的可以试一下以上代码

当元组有三个元素,但是你只需要中间一个元素,可以把第一个和第三个元素用其他变量去占位,到时候丢掉即可。

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

在这里插入图片描述
可用Python的*来解决这个问题。

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

当运行时你会发现,middle的输出结果类型为列表类型。
grades数据类型可为:列表、元组、字符串
比较适合可变长元组序列。
在这里插入图片描述
也可用在字符串:

lines = 'E:/python_work/pachong/crawler/ab.py'
*trailing, current = lines.split('/')
print(trailing)

'''
运行结果:
F:\python\python.exe E:/python_work/pachong/crawler/ab.py
['E:', 'python_work', 'pachong', 'crawler']

Process finished with exit code 0
'''

如果你够聪明也可用这种分割语法实现递归算法。

1.3保留最后N个元素

在这里插入图片描述
可以使用collections.deque
下面的代码在多行上面做简单的文本匹配,并返回匹配所在行的最后N行:
在这里插入图片描述
查询元素的代码时,通常会yield表达式的生成器函数。

使用**deque(maxlen=N)**构造函数会新建一个固定大小的队列。当新元素加入时会移除最先加入的元素。(队列的性质)

from collections import deque
q = deque(maxlen=3)
q.append(1)
print(q)
q.append(2)
q.append(3)
print(q)
q.append(4)
print(q)

#运行结果:
F:\python\python.exe E:/python_work/pachong/crawler/collections_deque.py
deque([1], maxlen=3)
deque([1, 2, 3], maxlen=3)
deque([2, 3, 4], maxlen=3)

Process finished with exit code 0

也可不设置队列大小,那么这个对列就无限大,可在队列两端执行添加和弹出元素的操作。

q = deque()
q.append(1)
q.append(2)
q.append(3)
print(q)
q.appendleft(4)
print(q)
print(q.pop())
print(q)
print(q.popleft())


#运行结果
F:\python\python.exe E:/python_work/pachong/crawler/collections_deque.py
deque([1, 2, 3])
deque([4, 1, 2, 3])
3
deque([4, 1, 2])
4

Process finished with exit code 0

在队列两端插入或删除元素的时间堵咋堵啊都是O(1),而在队列的开头插入或删除的时间复杂度为O(N).

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

在这里插入图片描述
使用heapq模块,heapq有两个函数:

nlargest():取最大值
nsmallest():取最小值

下面的代码用price的值进行比较

import heapq
nums = [1, 4, 5, 8, 9, 44, 55, 36, 85, 41, 1]
print(heapq.nlargest(3, nums))   #输出最大的三个值
print(heapq.nsmallest(3, nums))  #输出最小的三个值

protfolio  = [
    {'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, protfolio, key=lambda s: s['price'])
expensive = heapq.nlargest(3, protfolio, key=lambda s: s['price'])
print(cheap)
print(expensive)

heap = list(nums)
heapq.heapify(heap)
print(heap)
print(sorted(nums)[:11])
print(set(nums))

#运行结果:
F:\python\python.exe E:/python_work/pachong/crawler/module_heapq.py
[85, 55, 44]
[1, 1, 4]
[{'name': 'YHOO', 'shares': 45, 'price': 16.35}, {'name': 'FB', 'shares': 200, 'price': 21.09}, {'name': 'HPQ', 'shares': 35, 'price': 31.75}]
[{'name': 'AAPL', 'shares': 50, 'price': 543.22}, {'name': 'ACME', 'shares': 75, 'price': 115.65}, {'name': 'IBM', 'shares': 100, 'price': 91.1}]
[1, 1, 5, 8, 4, 44, 55, 36, 85, 41, 9]
[1, 1, 4, 5, 8, 9, 36, 41, 44, 55, 85]
{1, 4, 5, 36, 8, 9, 41, 44, 85, 55}

Process finished with exit code 0

下面代码为对列表进行一次堆排序,然后可以得到最小值heap[0],弹出的元素始终为该列表最小值最小。时间复杂度为O(logN).

nums = [1, 8, 3, 4, 5, 9, 6, 77, -54, 22]
import heapq
heap = list(nums)
heapq.heapify(heap)
print(heap)
#输出最小的三个元素
print(heapq.heappop(heap))  #输出第一个元素
print(heapq.heappop(heap))
print(heapq.heappop(heap))

小结:
当查找元素个数相对比较小,可用函数nlargest()和nsmallest().
当查找唯一最大或最小值,可用函数max()和min().
当N的大小接近集合一般先排序再切片可用sorted(items)[:N](前N个最小值)或sorted(items)[-N:](后N个最大值)。

1.5实现一个优先队列

在这里插入图片描述
使用heapq实现简单的优先级队列:

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)
print(q.pop())
print(q.pop())
print(q.pop())
print(q.pop())
运行结果:
F:\python\python.exe E:/python_work/pachong/crawler/priority_queue.py
Item('bar')
Item('spam')
Item('foo')
Item('grok')

Process finished with exit code 0

第一个pop()返回优先级最高的元素。相同优先级按照插入顺序返回。
讨论
函数heapq.heappus()he heapq.heappop()分别在独立额上插入和删除第一个元素,并且队列_queue第一个元素具有最高优先级。heappop()函数总是返回“最小(最小位置)”的元素。push和pop操作复杂度都是O(logN),N是堆的大小。

1.6字典中的键映射多个值

在这里插入图片描述
在这里插入图片描述
该字典使用列表还是集合取决于你的实际需要。如果你想保持插入顺序,那么就用列表;如果想你想消除重复元素那么使用集合。
那么可以使用collections模块中的defaultdict来构造这样的字典。defaultdict会总动初始化每个key刚开始对应的值,所以你需要关注添加元素操作。

from collections import defaultdict

d = defaultdict(list)
d['a'].append(1)
d['a'].append(2)
d['b'].append(4)
print(d)

d = defaultdict(set)
d['a'].add(1)
d['a'].add(2)
d['b'].add(4)
print(d)
#运行结果:
F:\python\python.exe E:/python_work/pachong/crawler/clooections_defaultdict.py
defaultdict(<class 'list'>, {'a': [1, 2], 'b': [4]})
defaultdict(<class 'set'>, {'a': {1, 2}, 'b': {4}})

Process finished with exit code 0

defaultdict会自动创建要访问的键创建映射实体。如果不需要,则可用setdefault()方法来替代。

d = {}
d.setdefault('a', []).append(1)
d.setdefault('a', []).append(2)
d.setdefault('b', []).append(4)
print(d)
运行结果:
{'a': [1, 2], 'b': [4]}

那么创建一个多映射字典就很简单了

d = defaultdict(list)
for key, value in pairs:
	d[key].append(value)

1.7字典排序

在这里插入图片描述
为了控制一个字典中的顺序,可以使用collections模块中的OrdereDict类,在迭代在操作的时候他会保持元素插入时的顺序。

from collections import OrderedDict

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

for key in d:
    print(key, d[key])

在这里插入图片描述
讨论
OrdereDict内部维护着一个根据键插入顺序排序的双向链表,每次当一个新的元素插入时,把它放在链尾。对于一个已经存在的键的重复赋值不会改变键的顺序。
OrdereDict的大小是普通字典的两倍,因为它内部维护着一个链表。

1.8 字典的运算

在这里插入图片描述
在这里插入图片描述
使用zip函数将键和值反转,再查找最小和最大股票价格和股票值的代码。

min_price = min(zip(prices.values(),prices.keys()))
# min_price is (10.75, 'FB')
max_price = max(zip(prices.values(),prices.keys()))
# max_price is (612.78, 'AAPL')

#使用sorted()函数排列字典数据
prices_sorted = sorted(zip(prices.values(), price.keys()))
# prices_sorted is [(10.75, 'FB'), (37.2, 'HPQ'),
#					(45.23, 'ACME'), (205.55, 'IBM'),
#					(612.78, 'AAPL')]

zip()函数创建的是一个只能访问一次的迭代器。
zip()函数,zip(值values,键keys)
讨论
在这里插入图片描述
但是如果还想要得到最小值

min_value = prices[min(prices, key = lambda k: prices[k])]

1.9查找量子点的相同点

在这里插入图片描述

a = {
    'x': 1,
    'y': 2,
    'z': 3
}
b = {
    'w': 10,
    'x': 11,
    'y': 2
}
print(a.keys() & b.keys())
print(a.keys() - b.keys())
print(a.items() & b.items())

c = {key: a[key] for key in a.keys() - {'z', 'w'}}
print(c)
#运行结果:
F:\python\python.exe E:/python_work/pachong/crawler/one/dict_equals.py
{'y', 'x'}
{'z'}
{('y', 2)}
{'y': 2, 'x': 1}

Process finished with exit code 0

字典就是键集合和值集合的映射,字典的keys()就是键视图对象,字典的items()是字典中中每项(包括键和值)的元素视图对象,可以对其进行并、交和差的运算。values()就是值视图对象,,他不支持这里介绍的集合操作,是因为值视图不能保证所有的值是不同的,可以先使用set再操作。

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

在这里插入图片描述
可以使用集合或者生成器来解决。

def deque(items):
    seen = set()
    for item in items:
        if item not in seen:
            yield item
            seen.add(item)

a = [1, 5, 5, 8, 9, 6, 2, 1, 7, 1]
print(list(deque(a)))

#运行结果
F:\python\python.exe E:/python_work/pachong/crawler/one/deque.py
[1, 5, 8, 9, 6, 2, 7]

Process finished with exit code 0

这里只能是元素为hashable(不可变)的时候才管用。但如果是不可哈希的序列呢?

def deque(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)

a = [{'x':1, 'y':2}, {'x':1, 'y':3}, {'x':1, 'y':2},{'x':2, 'y':4}]
print(list(deque(a, key=lambda d: (d['x'], d['y']))))
print(list(deque(a, key=lambda d: d['x'])))

#运行结果
F:\python\python.exe E:/python_work/pachong/crawler/one/deque.py
[{'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 2, 'y': 4}]
[{'x': 1, 'y': 2}, {'x': 2, 'y': 4}]

Process finished with exit code 0

key参数指定函数,将序列元素转换为hashable类型。
set函数不能维护元素的是顺序。

1.11 命名切片

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值