V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
plko345
V2EX  ›  Python

请教两个小问题

  •  
  •   plko345 · 2023-03-11 08:10:57 +08:00 · 2242 次点击
    这是一个创建于 618 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题一

    # 相同类型的实例列表, 实例有一个 `int` 类型的 `num` 属性
    ins = [in1, in2, in3, in4, in5, in6, ...]
    

    每个实例都有一个 int 类型的 num 属性, 在 不使用 一些额外库找到 num 相同的, 应该怎么做

    # 我的方法
    tmp_dict = {}
    for i in ins:
        if not tmp_dict.get(i.num):
            tmp_dict[i.num] = []
        tmp_dict[i.num].append(i)
    

    有什么更好的办法吗?

    问题二

    代码里面有比较多的 for 语句, 要不要刻意把这些都 "优化" 成 map/filter/... 的语句(算函数式编程吗)?

    14 条回复    2023-03-11 16:35:32 +08:00
    locoz
        1
    locoz  
       2023-03-11 08:28:43 +08:00   ❤️ 1
    这种常规问题建议直接找 ChatGPT ,它学太多了。
    Trim21
        2
    Trim21  
       2023-03-11 08:32:57 +08:00   ❤️ 1
    问题一 用 collections.defaultdict
    cmdOptionKana
        3
    cmdOptionKana  
       2023-03-11 08:34:13 +08:00   ❤️ 1
    建议转为 map/filter 之类的,自己体验一下,这样做一段时间,又使用 for 循环来做类似的事情,此时,你自己就会有非常清晰的判断,哪一种写法更好,因为你都真实体验过了。
    jsjjsyc
        4
    jsjjsyc  
       2023-03-11 08:38:53 +08:00 via Android   ❤️ 1
    问题一用自带库 itertools 的 groupby:
    result = groupby(ins, lambda x:x.num)

    问题二我也很好奇,不知道这样写能不能提高运行速度,等大佬回答吧🤣
    beeeeeeat
        5
    beeeeeeat  
       2023-03-11 08:40:12 +08:00 via iPhone   ❤️ 1
    1. for 循环里可以用 1 行替换
    tmp_dict.setdefault(i.num, []).append(i)

    2. 你贴的代码里只有 1 个循环,而且没有收集返回值,不用 map 等方法。如果其他有需要惰性计算的地方可以用。
    icatme
        6
    icatme  
       2023-03-11 08:55:42 +08:00
    for 遍历查找平均复杂度 n/2 吧, Map 之类查找复杂度一般是 log n, 但添加会有点额外开销
    icatme
        7
    icatme  
       2023-03-11 08:58:59 +08:00
    抱歉啊, 不熟 python,上面说的不是对 Python 的 .... 没注意看语言
    renmu
        8
    renmu  
       2023-03-11 09:23:25 +08:00 via Android
    1. 不管怎么找总是要遍历一次,你的实现没什么问题,无非可以用糖少几行代码。
    2. 没有必要
    dlsflh
        9
    dlsflh  
       2023-03-11 09:42:17 +08:00 via Android
    别整那些花里胡哨的,过几天自己又看不懂了。
    lixiang2017
        10
    lixiang2017  
       2023-03-11 14:35:12 +08:00
    代码示例
    ```Python3
    from random import choice
    from collections import defaultdict
    from itertools import groupby


    class Instance:
    def __init__(self, num) -> None:
    self.num = num


    arr = list(range(4))
    instances = [Instance(choice(arr)) for _ in range(10)]
    print("values ", [instance.num for instance in instances])
    # values [3, 2, 3, 2, 3, 1, 3, 1, 3, 2]

    # use defaultdict
    pair1 = defaultdict(list)
    for instance in instances:
    pair1[instance.num].append(instance)

    # use groupby # wrong! need to sort by num first
    groups = groupby(instances, lambda instance: instance.num)
    pair2 = {x: list(g) for x, g in groups}

    assert pair1 != pair2 # also probably equal

    # use groupby # wrong! need to sort by num first
    instances.sort(key=lambda instance: instance.num)
    groups2 = groupby(instances, lambda instance: instance.num)
    pair3 = {x: list(g) for x, g in groups2}

    assert pair1 == pair3
    ```
    lixiang2017
        11
    lixiang2017  
       2023-03-11 14:39:05 +08:00
    v2 貌似不支持 markdown
    https://pastebin.com/XTnpF56F
    lixiang2017
        12
    lixiang2017  
       2023-03-11 14:45:00 +08:00   ❤️ 1
    再说点别的。
    1. not tmp_dict.get(i.num) 是有问题的。i.num 可能为 0, not tmp_dict.get(i.num) 此时为 True 。
    变量命名尽量不要用 tmp ,尽量用有实际意义。i 一般是用作索引下标,建议别混用。
    2. 最内层的一两层倒也可以简写。多层就不建议了。python 这几个 built-in 的语法糖不是链式的,多层嵌套反而降低可读性。
    lixiang2017
        13
    lixiang2017  
       2023-03-11 14:53:59 +08:00
    呃,上面最后一点的注释写错了。后一个 sort+groupby 是对的
    plko345
        14
    plko345  
    OP
       2023-03-11 16:35:32 +08:00
    @lixiang2017 多谢大佬详细的解答
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   995 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 606ms · UTC 21:27 · PVG 05:27 · LAX 13:27 · JFK 16:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.