36

我喜欢 python 处理变量交换的方式: a, b, = b, a

我也想使用这个功能在数组之间交换值,不仅是一次一个,而且是多个(不使用临时变量)。这不是我所期望的(我希望沿第三维的两个条目都可以交换):

import numpy as np
a = np.random.randint(0, 10, (2, 3,3))
b = np.random.randint(0, 10, (2, 5,5))
# display before
a[:,0, 0]
b[:,0,0]
a[:,0,0], b[:, 0, 0] = b[:, 0, 0], a[:,0,0] #swap
# display after
a[:,0, 0]
b[:,0,0]

有人有想法吗?当然,我总是可以引入一个额外的变量,但我想知道是否有更优雅的方法来做到这一点。

4

4 回答 4

27

Python 正确地解释了代码,就好像你使用了额外的变量一样,所以交换代码相当于:

t1 = b[:,0,0]
t2 = a[:,0,0]
a[:,0,0] = t1
b[:,0,0] = t2

但是,即使代码也不能正确交换值!这是因为 Numpy切片不会急切地复制数据,它们会在现有数据中创建视图。仅在分配切片时执行复制,但在交换时,没有中间缓冲区的复制会破坏您的数据。这就是为什么您不仅需要一个额外的变量,还需要一个额外的 numpy 缓冲区,这是一般 Python 语法一无所知的原因。例如,这按预期工作:

t = np.copy(a[:,0,0])
a[:,0,0] = b[:,0,0]
b[:,0,0] = t
于 2013-02-18T10:18:31.150 回答
11

我觉得这是最简单的:

a[:,0,0], b[:, 0, 0] = b[:, 0, 0], a[:, 0, 0].copy() #swap

时间比较:

%timeit a[:,0,0], b[:, 0, 0] = b[:, 0, 0], a[:, 0, 0].copy() #swap
The slowest run took 10.79 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 1.75 µs per loop

%timeit t = np.copy(a[:,0,0]); a[:,0,0] = b[:,0,0]; b[:,0,0] = t
The slowest run took 10.88 times longer than the fastest. This could mean that an intermediate result is being cached 
100000 loops, best of 3: 2.68 µs per loop
于 2015-10-27T07:23:01.193 回答
1

user4815162342 的答案确实是“正确”的答案。但如果你真的追求单线,那么考虑一下:

a[arange(2),0,0], b[arange(2), 0, 0] = b[arange(2), 0, 0], a[arange(2),0,0] #swap

然而,这明显降低了效率:

In [12]: %timeit a[arange(2),0,0], b[arange(2), 0, 0] = b[arange(2), 0, 0], a[arange(2),0,0]
10000 loops, best of 3: 32.2 µs per loop

In [13]: %timeit t = np.copy(a[:,0,0]); a[:,0,0] = b[:,0,0]; b[:,0,0] = t
The slowest run took 4.14 times longer than the fastest. This could mean that an intermediate result is being cached 
100000 loops, best of 3: 13.3 µs per loop

(但请注意关于“最慢运行”的注释...如果您尝试使用“-n 1 -r 1”调用 %timeit,您将看到更多可比较的结果 - 尽管我的解决方案仍然慢了约 50% - 演示是的,缓存正在影响时间)

于 2015-03-11T13:43:52.577 回答
-1

这将起作用。

a[:,0,0], b[:, 0, 0] = b[:, 0, 0].copy(), a[:, 0, 0].copy()
于 2016-07-02T07:40:01.623 回答