• 数据结构与算法 (04)


    还是继续一些, PythonCook 的基本操作, 其实真正涉及, 如标题所言的, 数据结构和算法的东西并不多, 想了想, 还是单独弄一个系列来用 Python实现各种数据结构和算法比较靠谱一些.

    从字典中提取子集

    需求

    从字典中去过滤或者提取其子集 (也是一个 dict)

    方案

    最简单的方式就是用 字典推导式.

    prices = {
        'ACME': 45.23,
        "AAPL": 612.78,
        "IBM": 37.20,
        "FB": 10.75
    }
    
    # make a dict of all prices over 200
    dict_01 = {key: value for key, value in prices.items() if value > 200}
    # make a dict of tech stocks
    tech_names = {"AAPL", 'IBM', "HPQ", 'MSFT'}
    dict_02 = {k:v for k, v in prices.items() if k in tech_names}
    
    print(dict_01)
    print(dict_02)
    
    {'AAPL': 612.78}
    {'AAPL': 612.78, 'IBM': 37.2}
    

    大多时候, 字典推导式能做到的, 通过一个元组序列, 然后将其传递给 dict() 也是可以是哦.

    dict((key, value) for key, value in prices.items() if value > 30)
    
    {'ACME': 45.23, 'AAPL': 612.78, 'IBM': 37.2}
    

    这样也行, 但还是不如字典推导式直观, 效率也是一般. 对于 第二个例子, 也可这样来重写.

    tech_names = {"AAPL", 'IBM', "HPQ", 'MSFT'}
    
    {key: prices[key] for key in prices.keys() & tech_names}
    
    {'AAPL': 612.78, 'IBM': 37.2}
    

    转换并同时计算数据

    需求

    处理序列时, 需要同步进行, 聚合运算. 如 sum(), min(), max() . 但前提是需要先转换或者 filter 数据

    方案

    我认为, 一个最为优雅的方式是, 使用一个生成器表达式参数. 比如, 现在我们想计算平方和.

    nums = [1, 2, 3, 4, 5]
    s = sum(x * x for x in nums)
    print(s)
    
    55
    

    再来几个 demo, 比如, 文件类型判断, 判断该文件是否为 .py

    import os 
    
    files = os.listdir()
    if any(name.endswith('.py') for name in files):
        print("There be Python!")
    else:
        print("Sorry, no Python!")
    
    Sorry, no Python!
    

    将序列拼接为 CSV 文件格式.

    # output a tuple as CSV
    s = ('Alice', 50, 134.5)
    print((','.join(str(x) for x in s)))
    
    Alice,50,134.5
    

    或者解析一个数据结构, 同样是边解析, 边计算的操作. 如要找出最小的价格来.

    portfolio = [
        {'name':"GOOG", "shares":50},
        {'name':"YDOO", "shares":60},
        {'name':"AOG", "shares":75},
        {'name':"SCOX", "shares":66}
    ]
    
    min_shares = min(s['shares'] for s in portfolio)
    print(min_shares)
    
    50
    

    生成器表达式, 果然是非常优雅的哦.

    s = sum((x * x for x in nums)) # 传递一个生成器表达式对象
    s = sum(x * x for x in nums) # 更优雅在于, 省略了括号
    

    我平时总是优先用列表来各种操作. 其实想想, 用生成器应该会更好, 更加节省内存哦. 以前代码是这样的风格的.

    # old
    def func_test(lst):
        ret = []
        for i in lst:
            ret.append(i)
        return ret 
    
    # test
    print(func_test([1,2,3,4]))
    
    [1, 2, 3, 4]
    

    现在呢, 不用写函数, 优先用生成器 yield 来弄呀. yield 后面的代码, 还能运行, 又能节省内存, 真的是可以哦.

    # new
    def gen_test(lst):
        for i in lst:
            yield i 
            # 还能继续往下, 厉害吧
            print(666)
            
    # test
    print(list(gen_test([1, 2, 3, 4])))
    
    666
    666
    666
    666
    [1, 2, 3, 4]
    

    合并多个字典或映射

    需求

    对于多个字典或者映射, 需将其从逻辑上, 合并为一个单一的映射后, 再执行某些操作, 比如查找键, 值是否存在.

    方案

    用 collections.ChainMap 类.

    假如我有如下两个字典:

    a = {'x':1, 'z':3}
    b = {'y':2, 'z':4}
    

    现在呢, 需要再两个字典中进行查找 (比如先从 a 中找, 如果找不到,再在 b 中找). 一个非常简单的方案是用内置的 collections 模块中的 ChainMap 类.

    from collections import ChainMap
    
    a = {'x':1, 'z':3}
    b = {'y':2, 'z':4}
    
    c = ChainMap(a, b)
    
    print(c['x'])
    print(c['y'])
    print(c['z'])
    
    1
    2
    3
    

    我觉得, 自己写个循环也能一样的效果呀, 并未觉得有啥高明的地方.

    一个 ChainMap 对象, 接收多个字典, 并将其在逻辑上变为一个字典. 这些字典并不是真正合并在一起了, ChainMap 类只是在内部创建了一个容纳这些字典的列表, 并重新定义了一些常见的字典操作来遍历该列表. 还行吧, 目前我自己倒是从来没用过.

    print(len(c))
    print(list(c.values()))
    
    3
    [2, 3, 1]
    

    小结

    • 字典中取子集, 多用字典推导式 {k: v for k, v in d.items() if xxxx}
    • 多用生成器表达式来做, 边转换和边计算, 尤其是, 自己以后写函数, 优先考虑生成器 yield
    • 合并字典 ChainMap 类, 其实也就那样, 自己写也是一样的简单, 没啥意思
  • 相关阅读:
    WebStorm破解方法
    jQuery学习笔记2
    jquery.js 3.0报错, Uncaught TypeError: url.indexOf is not a function
    animate.css –齐全的CSS3动画库--- 学习笔记
    MySQL数据库---表的操作
    MySQL数据库---库的操作
    MySQL数据库---前言
    CppUnit使用和源码解析
    代码覆盖率检查
    代码Verify简介
  • 原文地址:https://www.cnblogs.com/chenjieyouge/p/12891936.html
Copyright © 2020-2023  润新知