36

Python が変数のスワップを処理する方法が気に入っています。 a, b, = b, a

そして、この機能を使用して、一度に1つだけでなく、配列間で値を交換したいと思います(一時変数を使用せずに)。これは私が期待したものではありません (3 番目の次元に沿った両方のエントリが両方に入れ替わることを望んでいました):

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 に答える
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 に答える