这段代码在 Python 里能怎么改写成效率更高的吗,听说 for 循环比较慢
xs = []
ys = []
zs = []
for data in ls:
_x, _y, _z = data
xs.append(_x)
ys.append(_y)
zs.append(_z)
用 numpy
xs = ls[:,0]
ys = ls[:,1]
zs = ls[:,2]
ls = numpy.array(ls)
等待 python3.11 版本,听说有一倍速度的提升🐶
不是数字呃,numpy 能处理非数字吗
不太清楚具体需求,也许可以让 xs,ys,zs 变成迭代器而不是 list ?
不考虑数组转 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
参考:
stackoverflow.com/questions/8081545/how-to-convert-list-of-tuples-to-multiple-lists
zip 怎么样
for 循环不知道怎么去掉,但是有一个提速的方法,list 初始化的时候带上长度
xs = [None] * len(data)
对于比较大的 list,可以快那么几十毫秒。。
用列表推导
xs=[data[0] for data in ls]
ys=[data[1] for data in ls]
zs=[data[2] for data in ls]
用 map 运算
xs = map(lambda data: data[0], ls)
ys = map(lambda data: data[1], ls)
zs = map(lambda data: data[2], ls)
你这把一个循环变成了三个, 应该只会更慢吧
O(n)了还优化个啥
不知道怎么优化,不过代码可以精简一下
for _x, _y, _z in ls:
xs.append(_x)
ys.append(_y)
zs.append(_z)
C++程序员的思路:预先分配下内存防止移动?
你要全部遍历一遍,这个算法已经 O(n),除了直接提速 for 和 append,可以用另外一种思路,就是看你的 xs,ys,zs 的用处,用 yield 把它改成生成器,类似 python2 里 range 到 xrange 的改变。
如果 ls 不变,进一步的优化可以加缓存,用 JSON 存到本地,第二次直接读取 JSON,虽然本身并没有优化到算法。
因为这个操作在 numpy 里面是 constant 的。。通过数据结构实现的。这也就是为什么你把 list 转成 np 的时间非常高的原因。当然了,你也可以试试看把处理好的 xs ys zs 再转成 list,还是很费时间。
np 本身的 dataframe 非常复杂也非常大
其实是一个 90 度旋转二维数组的过程,用 Python 的内置函数实现应该会更快,因为毕竟底层是 C 。
可以先 rotated = list(zip(*ls[::])) 旋转一下二维数组,再 xs.extend(rotated) .
跑起来大概提高了一倍的速度
imgur.com/e602lpH
Python 的优化就是有些反常识,3 个循环不一定比 1 个循环慢,具体还是看解释器怎么跑
预分配内存在 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]
好吧,#17 我服了
我测了一下,zip 稍快一些
blob: imgur.com/0782fae0-e12e-46fe-a6ea-0db5e1e39c72
同意,你的版本更快,
In [101]: def t1(ls):
...: flat = list(itertools.chain.from_iterable(ls))
...: xs = flat[::3]
...: ys = flat[1::3]
...: zs = flat[2::3]
...: return xs, ys, zs
...:
In [102]: def t2(ls):
...: xs, ys, zs =list(zip(*ls))
...: return list(xs), list(ys), list(zs)
In [113]: ls=[[i, i+1, i+2] for i in range(1, 98, 3)]
In [114]: %timeit t1(ls)
4.26 µs ± 17.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [115]: %timeit t2(ls)
3.2 µs ± 19.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
其实省掉 extend 过程,直接返回数组的话,还能再提高点性能
🤝 其实大家思路都差不多,python 要提高效率的话,应该尽可能的使用内置函数
对,就是这个道理,内置函数底层执行更快 🤝
#19 学习了。
#19 楼 一行代码开启新世界
def func4(ls):
xs = list(islice(chain.from_iterable(ls), 0, None, 3))
ys = list(islice(chain.from_iterable(ls), 1, None, 3))
zs = list(islice(chain.from_iterable(ls), 2, None, 3))
def func5(ls):
xs = list(compress(chain.from_iterable(ls), cycle([1, 0, 0])))
ys = list(compress(chain.from_iterable(ls), cycle([0, 1, 0])))
zs = list(compress(chain.from_iterable(ls), cycle([0, 0, 1])))
itertools 里的内置函数速度都还可以
ls[::] 是干嘛?我怎么看不懂啊,求教,另外为什么我测的是列表推导式更快一点,数量级越大越明显
另外,只有在 data=[(x,y,z),(x2,y2,z2,...)] 为元祖 zip 才会有明显速度优势,
data[(x,y,z),(x2,y2,z2,...)] range(100000)
for: spend_time:0.03163599967956543
列表推导式:spend_time:0.012620925903320312
zip: spend_time:0.0060007572174072266
data[(x,y,z),(x2,y2,z2,...)] range(100000)
for: spend_time:0.03195595741271973
列表推导式:spend_time:0.012039899826049805
zip: spend_time:0.016546964645385742
xs, ys, zs = zip(*ls)
开发环境没有最好,只有最合适。自己用的顺手就好。开贴只是简单记录一下自己的折腾结果。 关于我自己:全栈开发。主要是 Go ,Vue ,有时有还有一些 C# 和 rust 。Vi…
开着开着满屏故障还是有点怕的,这要是飞机报这么一堆 WARNING CAS 不知道飞行员是啥心情。 吃瓜吃瓜 懒得辨了 什么时候刹车助力故障变成了刹车失灵?助力丢失下你就得…
我于2014年8月3日周六的上午在微博、twitter、CoolShell上发布了一个和程序员有关的解谜题的活动——【活动】解谜题送礼物。我使用了二级域名fun.coolshe…