这段代码在 Python 里能怎么改写成效率更高的吗,听说 for 循环比较慢

2021-10-07 09:08:34 +08:00
 zxCoder
    xs = []
    ys = []
    zs = []
    for data in ls:
        _x, _y, _z = data
        xs.append(_x)
        ys.append(_y)
        zs.append(_z)
6443 次点击
所在节点    Python
33 条回复
fuis
2021-10-07 09:16:43 +08:00
用 numpy

xs = ls[:,0]
ys = ls[:,1]
zs = ls[:,2]
fuis
2021-10-07 09:17:27 +08:00
ls = numpy.array(ls)
ChrisFreeMan
2021-10-07 09:24:41 +08:00
等待 python3.11 版本,听说有一倍速度的提升🐶
zxCoder
2021-10-07 09:26:55 +08:00
@fuis 不是数字呃,numpy 能处理非数字吗
vcfghtyjc
2021-10-07 09:31:18 +08:00
不太清楚具体需求,也许可以让 xs,ys,zs 变成迭代器而不是 list ?
zacharyjia
2021-10-07 09:31:50 +08:00
不考虑数组转 np array 的这个开销的话,1 楼的 numpy 确实非常快:

Using numpy: 0.00000000s
Using append: 0.36167359s


加上转 np 的开销嘛,就不一样了:

Using numpy: 1.69339228s
Using append: 0.37969041s


其实 append 还是挺快的,比非常 Pythonic 的*zip 的方法要快挺多了:
Using *zip: 1.30143762s
Using append: 0.39510083s


参考:
https://stackoverflow.com/questions/8081545/how-to-convert-list-of-tuples-to-multiple-lists
catbaron
2021-10-07 10:00:53 +08:00
zip 怎么样
fatestigma
2021-10-07 10:10:59 +08:00
for 循环不知道怎么去掉,但是有一个提速的方法,list 初始化的时候带上长度
xs = [None] * len(data)
对于比较大的 list,可以快那么几十毫秒。。
ch2
2021-10-07 10:14:25 +08:00
用列表推导
xs=[data[0] for data in ls]
ys=[data[1] for data in ls]
zs=[data[2] for data in ls]
ch2
2021-10-07 10:18:14 +08:00
用 map 运算
xs = map(lambda data: data[0], ls)
ys = map(lambda data: data[1], ls)
zs = map(lambda data: data[2], ls)
guoqiao
2021-10-07 10:40:02 +08:00
@ch2 你这把一个循环变成了三个, 应该只会更慢吧
WhoMercy
2021-10-07 11:13:02 +08:00
O(n)了还优化个啥
fancy967
2021-10-07 12:00:32 +08:00
不知道怎么优化,不过代码可以精简一下
for _x, _y, _z in ls:
xs.append(_x)
ys.append(_y)
zs.append(_z)
dangyuluo
2021-10-07 12:02:14 +08:00
C++程序员的思路:预先分配下内存防止移动?
cyrbuzz
2021-10-07 12:39:46 +08:00
你要全部遍历一遍,这个算法已经 O(n),除了直接提速 for 和 append,可以用另外一种思路,就是看你的 xs,ys,zs 的用处,用 yield 把它改成生成器,类似 python2 里 range 到 xrange 的改变。

如果 ls 不变,进一步的优化可以加缓存,用 JSON 存到本地,第二次直接读取 JSON,虽然本身并没有优化到算法。
MintZX
2021-10-07 13:18:44 +08:00
@zacharyjia 因为这个操作在 numpy 里面是 constant 的。。通过数据结构实现的。这也就是为什么你把 list 转成 np 的时间非常高的原因。当然了,你也可以试试看把处理好的 xs ys zs 再转成 list,还是很费时间。

np 本身的 dataframe 非常复杂也非常大
niubee1
2021-10-07 13:25:51 +08:00
其实是一个 90 度旋转二维数组的过程,用 Python 的内置函数实现应该会更快,因为毕竟底层是 C 。
可以先 rotated = list(zip(*ls[::])) 旋转一下二维数组,再 xs.extend(rotated) .

跑起来大概提高了一倍的速度

https://imgur.com/e602lpH
NoAnyLove
2021-10-07 13:28:28 +08:00
@guoqiao Python 的优化就是有些反常识,3 个循环不一定比 1 个循环慢,具体还是看解释器怎么跑
@dangyuluo 预分配内存在 Python 优化中通常效果不佳,因为通常不是主要因素

如果 ls 足够长的话,比如 ls=[[i, i+1, i+2] for i in range(1, 98, 3)],那么这个版本可能更快一些,

flat = list(itertools.chain.from_iterable(ls))
xs = flat[::3]
ys = flat[1::3]
zs = flat[2::3]
niubee1
2021-10-07 13:28:37 +08:00
NoAnyLove
2021-10-07 13:32:13 +08:00
好吧,#17 我服了

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

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

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

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

© 2021 V2EX