请教两个小问题

2023-03-11 08:10:57 +08:00
 plko345

问题一

# 相同类型的实例列表, 实例有一个 `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/... 的语句(算函数式编程吗)?

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

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

2. 你贴的代码里只有 1 个循环,而且没有收集返回值,不用 map 等方法。如果其他有需要惰性计算的地方可以用。
icatme
2023-03-11 08:55:42 +08:00
for 遍历查找平均复杂度 n/2 吧, Map 之类查找复杂度一般是 log n, 但添加会有点额外开销
icatme
2023-03-11 08:58:59 +08:00
抱歉啊, 不熟 python,上面说的不是对 Python 的 .... 没注意看语言
renmu
2023-03-11 09:23:25 +08:00
1. 不管怎么找总是要遍历一次,你的实现没什么问题,无非可以用糖少几行代码。
2. 没有必要
dlsflh
2023-03-11 09:42:17 +08:00
别整那些花里胡哨的,过几天自己又看不懂了。
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
2023-03-11 14:39:05 +08:00
v2 貌似不支持 markdown
https://pastebin.com/XTnpF56F
lixiang2017
2023-03-11 14:45:00 +08:00
再说点别的。
1. not tmp_dict.get(i.num) 是有问题的。i.num 可能为 0, not tmp_dict.get(i.num) 此时为 True 。
变量命名尽量不要用 tmp ,尽量用有实际意义。i 一般是用作索引下标,建议别混用。
2. 最内层的一两层倒也可以简写。多层就不建议了。python 这几个 built-in 的语法糖不是链式的,多层嵌套反而降低可读性。
lixiang2017
2023-03-11 14:53:59 +08:00
呃,上面最后一点的注释写错了。后一个 sort+groupby 是对的
plko345
2023-03-11 16:35:32 +08:00
@lixiang2017 多谢大佬详细的解答

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/923068

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX