python学习进阶--3 python的数据结构及操作

基础的大概懂了,剩下的就是那些比较奇特的,有用的用法,这也是一本火热的进阶书籍上一点一点学的,也有些年头了

# region 1.1 序列的拆分
# 迭代的元组,数组都可以拆分,还可以使用_代表无用的拆分变量
data = ['song', '50', '1.76', {'2012', '12', '3'}]
name, weight, tall, time = data

kewen = 'HELLO'
a, b, c, d, e = kewen
# endregion

# region 1.2 任意长度迭代数据的拆分
# 从多余N个的元素中分解出N个
grade = [100, 23, 54, 54, 12, 99]
first, *middle, last = grade  # 得到的是中间的四个

record = ['wang', 'dava.com', 'londo street', '223-344522', '321-343123']
name, com, house, *telephone = record  # 成功提取

record = ['acm', 54, 2.43, (12, 18, 2018)]
name, *_, (*_, year) = record

# endregion

# region  1.3 队列
# 创建制定大小的队列 老的会被覆盖
from collections import deque
q = deque(maxlen=3)
q.append(1)
q.append(2)
q.append(3)
q
q.append(4)
q
# 队列也可以无限长
# 并且左右都可以弹出或者添加
q = deque()
q.appendleft(3)
q.popleft()

# endregion

# region  1.4 找到最大最小的N个元素
import heapq
nums = [19, 3, 76, 32, 54, 21, 8, 43, 7]
print(heapq.nlargest(3, nums))
print(heapq.nsmallest(3, nums))

# 该函数还接收参数key 使得还可以接受更复杂的操作
protfolio = [{'name': 'songyu', 'weight': 50, 'hight': 121},
             {'name': 'lixinrui', 'weight': 48, 'hight': 132},
             {'name': 'sunzhezheng', 'weight': 51, 'hight': 141},
             {'name': 'chenxin', 'weight': 52, 'hight': 112}
             ]
print(heapq.nlargest(3, protfolio, key=lambda s: s['weight']))
print(heapq.nsmallest(3, protfolio, key=lambda s: s['hight']))

# 如果是单纯的找很多元素中的几个最小
heap = list(nums)
heapq.heapify(heap)  # 自动将最小的放在首位 复杂度logN
heapq.heappop(heap)  # 持续弹出最小的

# 总结
# 元素数量相对较小 nlargest这种比较适合
# 简单的找一个最大最小 min max更好
# N和本身差不多大是 使用sorted(items)[:N] 或者 sorted(items)[-N:]更好
# endregion

# region 1.5 优先级队列实现
import heapq
class PriorityQueue:
    def __init__(self):
        self.quene = []
        self.index = 0

    def push(self, item, priority):
        heapq.heappush(self.quene, (-priority, self.index, item))
        self.index += 1

    def pop(self):
        return heapq.heappop(self.quene)[-1]
# 关键的heappush始终让最大的priority在最前面 弹出时也是最小的先弹出来
# 元数组之间可以比较大小(3,'sd')(4,'fd') 但是第一个数字相同就会错误,所以引入了第二个index
q = PriorityQueue()
q.push('asongyu', 3)
q.push('haige', 4)
q.push('qiuqiu', 2)
q.pop()
# endregion

# region 1.6 字典的键映射到多个数值上去
# 一般的情况是使用数组等作为值
d = {'a': [1, 4, 6],
     'b': [5, 6]
}
e = {'a': {1, 4, 6},
     'b': {5, 6}
}
# 需要看情况 正常情况下保留插入顺序的就是用列表 不要求重复数值就集合
from collections import defaultdict
d = defaultdict(list)  # 列表方式
d['a'].append(1)
d['a'].append(2)
d['b'].append(4)

d = defaultdict(set)  # 集合方式
d['a'].add(1)
d['a'].add(2)
d['b'].add(4)

# 在正常的字典上也可以调用 方式如下
d = {}
d.setdefault('a', []).append(1)
d.setdefault('a', []).append(2)
# endregion

# region 1.7 保持顺序的字典
# 在对字典进行操作时保持添加时候的顺序 不会乱 序列化时有用!
from collections import OrderedDict
import json
d = OrderedDict()
d['songyu'] = 45
d['pianpian'] = 12
d['qingxin'] = 32
d['dianchi'] = 24
json.dumps(d)
# endregion

# region 1.8 字典键值寻找大小
price = {'a': 34,
         'b': 43,
         'c': 17,
         'd': 33
         }
# 使用zip可以将两个列表压缩为字典 配合max min sorted等可实现统计排序
print(max(zip(price.values(), price.keys())))
# 字典常见操作只是处理键,或者单独处理值,如何获取最大值得键呢? 使用key参数
max(price, key=lambda k: price[k])
# endregion

# region 1.9 两个字典寻找相同点 或者过滤
# 集合也可以做算术运算,长见识了
a = {'meat': 1,
     'cheese': 3,
     'vagetable': 2
     }
b = {'dog': 2,
     'meat': 1,
     'noodle': 5
     }
a.keys() & b.keys()
a.keys() - b.keys()
a.items() & b.items()
# 过滤字典 采用lamba表达式去掉键
c = {key: a[key] for key in a.keys() - {'meat'}}
# endregion

# region 1.10 移除序列的重复项且不变顺序
# 如果序列可哈希 则可以通过集合器和生成器完成
def dededupe(items):
    seen = set()
    for item in items:
        if item not in seen:
            yield item
            seen.add(item)
a = [1,3,5,6,4,12,4,3,1]
b = dededupe(a)
# 如果是不可哈希的字典等可以先转换类型
def dededupes(items, key=None):
    seen = set()
    for item in items:
        val = item if key in None else key(item)
        if item not in seen:
            yield item
            seen.add(val)
a = [{"x": 1, "y": 2}, {"x": 3, "y": 3}, {"x": 2, "y": 4}, {"x": 1, "y": 2}]
b = dededupes(a)
# 如果只想去除 不考虑顺序的话
set(a)  # 就可以
# endregion

# region  1.11 切片的命名
# 创建切片对象 可以对任何允许的类型进行切片
items = [1, 2, 3, 4, 5, 6, 7]
a = slice(2, 4)
items(a)
a = slice(1, 20, 1)      # 分别为初始 结束 步长
# 当应用于新的序列式 由于不知道大小 可能会出现越界等
# 这时候可以用indices(size)的方法进行映射
s = "helloword"
a.indices(len(s))
# endregion

# region 1.12 找出序列中出现次数最多的
from collections import Counter
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 3, 4, 2, 4, 6, 7, 3, 6, 8, 9, 5, 3, 5, 6, 3, 2, 4]
worrd_count = Counter(a)
top_three = worrd_count.most_common(a, 3)
# 底层为一个字典
b = worrd_count[1]
# 想增加计数的话可以直接加
worrd_count[1] += 1
# 令人惊讶的是他也支持直接加减 两个Counter
c = a + b
c = a - b
# endregion

# region  1.13 对字典进行规则排序
# operator的itemgetter可以实现这个功能   支持多个关键字
rows = [{"name": "songyu", "age": "12", "id": "20170011"}]
from operator import itemgetter
row_by_name = sorted(rows, key=itemgetter("name"))
row_by_nameandid = sorted(rows, key=itemgetter("name", "id"))

# 我们可以使用lamde表达式替代 但是这个更快一些
#  这个同样支持max min 返回第一个和最后一个
# endregion

# region 1.14 对类进行排序
# 对一个类进行排序 依靠类里面的变量值
class user:
    def __init__(self, userid):
        self.id = userid
userlist = [user(3), user(4), user(100)]
sorted(userlist, key=lambda k: k.id)
# 另一个更快的方式是attrgetter
from operator import attrgetter
sorted(userlist, key=attrgetter("id"))       # 支持多变量输入
# endregion

# region  1.15 将列表分组,然后迭代
from operator import itemgetter
from itertools import groupby
# 先排序, 在分组 将拥有相同值的分为一组
rows =[
    {"name": "dsa", "date": "07/04/2012"},
    {"name": "dsfda", "date": "07/01/2012"},
    {"name": "dsa", "date": "07/01/2012"},
    {"name": "dsfda", "date": "07/04/2012"},
      ]
rows.sort(key=itemgetter("date"))
for date, items in groupby(rows, key=itemgetter("date")):
    print(date)
    for item in items:
        print(item)
# endregion

# region 1.16 筛选列表元素
# 最简单的是列表推导
a = [2, 5, 12, -4, 8, -2, 10]
b = [n for n in a if n > 0]
# 如果是需要考虑不同情况的过滤 使用内建filter 自己构建过滤函数
values = ["1", "3", "-2", "N/A", "-"]
def adjust_is_int(value):
    try:
        x = int(value)
        return True
    except ValueError:
        return False
# 判断每个值是否满足条件
result = list(filter(adjust_is_int, values))
print(result)

# 另外一种情况是不剔除 而是替换
b = [n if n > 0 else 0 for n in a]

# 还有可以使用列表进行筛选
from itertools import compress
order = [1, 3, 6, 3, 6, 4]
lis = ["one", "two", "three", "four", "five", "six"]
choose = [n > 5 for n in order]
chooselist = list(compress(lis, choose))
# endregion

# region 1.17 从字典中提取子集
price = {"alice": 34.45, "peach": 432.5, "banana": 205.4, "meat": 89.6, "rbq": 426.3}
p1 = {key: value for key, value in price.items() if value > 200}
chooselist = {"peach", "meat", "rbq"}
p2 = {key: value for key, value in price.items() if key in chooselist}
# 下属方案虽然也可以完成 但是慢
p3 = dict((key, value) for key, value in price.items() if value > 200)
# endregion

# region 1.18 命名元组 按照名称创建和访问
# 提供名称和内部结构 就可以创建和访问了
from collections import namedtuple
msgtuple = namedtuple('msgtuple', ["address", "phonenum"])
sub = msgtuple("daqing", "13256146452")
sub.address
sub.phonenum

# endregion

# region 1.19 数据换算和转换同时
nums = [1, 2, 3, 4, 5]
s = sum(x * x for x in nums)

s = {"scm", 50, 23.3}
print(",".join(str(x) for x in s))

pro = [
    {"name": "apple", "price": 20},
    {"name": "peach", "price": 8},
    {"name": "banana", "price": 12},
]
min_shares = min(s["shares"] for s in pro)
min_shares = min(pro, key=lambda s: s["shares"])

# endregion

# region  1.20 多个映射合并为一个
# ChinaMap 只是简单的非组合 总是返回第一个字典的值,没有再去第二个找
# 会根据两个的改变而变  而字典的update不会根据原始的改变而改变
from collections import ChainMap
a = {"x": 1, "z": 2}
b = {"x": 2, "y": 3}
c = ChainMap(a, b)
# c拥有所有字典的操作和方法

merged = dict(b)
merged.update(a)
a["x"] = 12
# 此时是不会变的
# endregion
# region
# endregion

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值