欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第一章 数据结构与算法

程序员文章站 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



列表推导式,嵌套列表推导式的使用
相关标签: Pythoncookbook