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)