第一章 数据结构与算法

第一章 数据结构与算法

常用的数据结构应该直接用
另外有趣的一点是,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



列表推导式,嵌套列表推导式的使用

猜你喜欢

转载自blog.csdn.net/qq_37904945/article/details/80158231