第一章 数据结构与算法
程序员文章站
2022-05-28 15:03:33
...
第一章 数据结构与算法
常用的数据结构应该直接用
另外有趣的一点是,collections模块中包含比较多针对数据结构的解决方案
努力成为一名合格的调包侠
1.1 可迭代对象的分解元素
# 可迭代对象中分解元素(找到自己的需求元素)
# 解决方案,利用"*表达式"
def drop_first_last(grades):
first,*middle,last=grades # * 包含万物
return avg(middle)
line='nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false'
uname,*fields,homedir,sh=line.split(':')
uname,homedir,sh
('nobody', '/var/empty', '/usr/bin/false')
这个*很好用,*要学会使用,#可以说是指针分配了一个可变的存储的空间
但是这个还是对数据有一定了解之后,才能使用的方法
还可以利用其将其进行迭代
dataset=[1,2,3,4,5]
def sum(items):
head,*tail=items
return head+sum(tail) if tail else head
sum(dataset)
15
后面这个 if tail else end 借助这个好好理解一下递归思想
return 1+sum([2,3,4,5])
return 2+sum([3,4,5])
.. 3+sum([4,5])
4+sum([5])
5+sum[] # 如果没有后面的 if else语句,这就会返回一个错误值
// 5+sum[] if tail else head 这个时候tail值为0,返回head 这个时候head为5
// 相当于 sum(5)这个函数 return head=5
4+5
3+9(4+5)
.. 2+12(3+4+5)
1+14(2+3+4+5)
return 15
要注意的一点的是,这个函数其实并没有多大的实际意义,就当是理解递归函数的意义
1.3 保存最后N个元素
保存有限的历史记录 collections.deque几乎都可以完全应用
deque=double-ended queue 双端队列容器
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(lines)
# 这个程序没咋看懂
1.4 找到最大或最小的N个元素
其实还是模块的熟悉和应用
heapq模块中含有最大和最小函数
实话说,对于列表这一类还是比较鸡肋的,我可以用sorted()进行实现
可能对于字典这一类可能还是比较有用的
import heapq
nums=[1,7,12,34,-7,-4,32,45,21]
print(heapq.nlargest(2,nums))
print(heapq.nsmallest(3,nums))
# (n,iterable,key=none) 这个key还是比较重要的,可用于字典变量 value 值的排序
[45, 34]
[-7, -4, 1]
sorted_nums=sorted(nums,reverse=True)
# 输出前三个大数
sorted_nums[0:3]
[45, 34, 32]
1.8 与字典有关的计算问题
对于字典,可以利用zip()函数来将字典的 键及值进行反转 ,值在前 则可以利用值来进行排序
直接用sorted()来进行排序
需要注意的一点是,zip()是一个迭代器,只能够被消费一次,如果两次调用 就是产生 ValueError 错误
字典的默认处理是 键 但一般我们需求较多的都是处理一些字典的 值
可以利用 dict.values()的方法来需找字典的 值
利用lambda表达式来进行简化运算,减少定义的函数量
lambda 相当于一个匿名函数
对于字典,键 的操作比较多,键 支持基本的集合操作
1.10 从序列表中移除重复项
# 解决方案是,利用集合和生成器
def dedupe(items):
seen=set()
for item in items:
if item not in seen:
yield item
seen.add(item)
插曲:yeild 使用解析
yeild 函数在python 中被称之为generator 生成器
# 展示yield是功能及使用方法
def fab(max):
n,a,b=0,0,1
while n<max:
print b
a,b=b,a+b
n=n+1
# 上面是一个简单的程序,但是对于开发者来说,直接在函数中打印数字,导致函数可复用性较差
# fab函数返回None,其他函数无法获得该函数生成的数列
# 考虑内存的占用
class Fab(object):
def __init__(self,max):
self.max=max
self.n,self.a,self.b=0,0,1
def __iter__(self):
return self
def __next__(self):
if self.n<self.max:
r=self.b
self.a,self.b=self.b,self.a+self.b
self.n=self.n+1
return r
raise StopIteration()
# 这个函数通过next()函数不断返回数列的下一个数,内存占用始终为一个常数
# 我们想保持函数的简洁性,又要保持迭代器的效果,yield就派上用场来
def fab(max):
n,a,b=0,0,1
while n<max:
yield b
a,b=b,a+b
n=n+1
# >>> for n in fab(5):
# >>> print(n)
又一个插曲:(nested)list comprehensions (嵌套)列表推导式
# 列表推导式是一个强大的工具,像其他强大的工具一样,你必须格外的小心的区使用
# 例如,转换举证的行和列,矩阵的转置
mat=[[1,2,3],
[4,5,6],
[7,8,9],]
print([row[i] for row in mat] for i in [0,1,2])
for i in [0,1,2]:
for row in mat:
print (row[i],) # 这个实现不了换行
print
# 但是对于矩阵的转置可以利用内置函数来完成复杂的流程语句
# 函数zip()
# >>>zip(*mat)
# 这个就可以完成转置
<generator object <genexpr> at 0x7f8d781fdbf8>
1
4
7
2
5
8
3
6
9
列表推导式,为了不被绕晕,一般都是从左向右读
如果只是简单的除去重复项,就可以构建一个集合
但是这种方法不能保证元素间的顺序不变,因此得到的结果会被打乱.
集合的特点就是,集合中的元素都是唯一的,但不保证他们之间的顺序.
1.12 序列中出现次数最多的元素
当面对任何需要对数据制表或计数的问题时,都要想起Counter这个助手
from collections import Counter
还有一些常用的
from operator import itemgetter
from itertools import groupby
# fliter()函数的理解和应用
def is_int(val):
try:
x=int(val)
return True
except ValueError:
return False
fliter(functions,sequence)
# 函数会 return 一个sequence队列
1.16 筛选序列中的元素
# 列表推导式和生成器表达式是用来筛选数据最简单和最直接的方式.也具有对数据进行转换的能力
mylist=[1,9,-3,-7,8,4,-2]
import math
print([math.sqrt(n) for n in mylist if n>0])
newlist=[n if n>0 else 0 for n in mylist]
newlist
[1.0, 3.0, 2.8284271247461903, 2.0]
[1, 9, 0, 0, 8, 4, 0]
# 子典中提取子集
# 利用字典推导式(dictionary comprehension)
p={key:vlaue for key,value in dictionay.items() if value>200}
1.18 将名称映射到序列的元素中
# 命名元组 ,利用这个来减少结构中对位置的依赖性
# from collections import namedtuple
# collections.namedtuple() 是一个工厂方法,返回的是Python中标准元素的子类
# 注意一点就是namedtuple 是不可变的
1.20 将多个映射合并为一个映射
from collections import ChainMap
# chainmap 记录一个底层映射关系的列表
a={'x':1,'y':2}
b={'x':3,'z':4}
merged=dict(b)
merged.update(a)
merged['x']
# 这样需要构建一个完整的字典对象,任何一个原始字典作了修改,这个改变都不会反应到合并的字典中
# ChainMap 使用的就是原始的字典,可以进行实时的更新
merged=ChainMap(a,b)
1
列表推导式,嵌套列表推导式的使用