2

请教两个小问题

 1 year ago
source link: https://www.v2ex.com/t/923068
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

V2EX  ›  Python

请教两个小问题

  plko345 · 17 小时 38 分钟前 · 1131 次点击
# 相同类型的实例列表, 实例有一个 `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

locoz      17 小时 20 分钟前   ❤️ 1

这种常规问题建议直接找 ChatGPT ,它学太多了。
Trim21

Trim21      17 小时 16 分钟前   ❤️ 1

问题一 用 collections.defaultdict
cmdOptionKana

cmdOptionKana      17 小时 15 分钟前   ❤️ 1

建议转为 map/filter 之类的,自己体验一下,这样做一段时间,又使用 for 循环来做类似的事情,此时,你自己就会有非常清晰的判断,哪一种写法更好,因为你都真实体验过了。
jsjjsyc

jsjjsyc      17 小时 10 分钟前 via Android   ❤️ 1

问题一用自带库 itertools 的 groupby:
result = groupby(ins, lambda x:x.num)

问题二我也很好奇,不知道这样写能不能提高运行速度,等大佬回答吧🤣
beeeeeeat

beeeeeeat      17 小时 9 分钟前 via iPhone   ❤️ 1

1. for 循环里可以用 1 行替换
tmp_dict.setdefault(i.num, []).append(i)

2. 你贴的代码里只有 1 个循环,而且没有收集返回值,不用 map 等方法。如果其他有需要惰性计算的地方可以用。
icatme

icatme      16 小时 53 分钟前

for 遍历查找平均复杂度 n/2 吧, Map 之类查找复杂度一般是 log n, 但添加会有点额外开销
icatme

icatme      16 小时 50 分钟前

抱歉啊, 不熟 python,上面说的不是对 Python 的 .... 没注意看语言
renmu

renmu      16 小时 26 分钟前 via Android

1. 不管怎么找总是要遍历一次,你的实现没什么问题,无非可以用糖少几行代码。
2. 没有必要
dlsflh

dlsflh      16 小时 7 分钟前 via Android

别整那些花里胡哨的,过几天自己又看不懂了。
lixiang2017

lixiang2017      11 小时 14 分钟前

代码示例
```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

lixiang2017      11 小时 4 分钟前   ❤️ 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

lixiang2017      10 小时 55 分钟前

呃,上面最后一点的注释写错了。后一个 sort+groupby 是对的
plko345

plko345      9 小时 14 分钟前

@lixiang2017 多谢大佬详细的解答

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK