32

Is there something more efficient than the following code to swap two values of a numpy 1D array?

input_seq = arange(64)

ix1 = randint(len(input_seq))
ixs2 = randint(len(input_seq))

temp = input_seq[ix2]
input_seq[ix2] = input_seq[ix1] 
input_seq[ix1] = temp
Gioelelm
  • 2,645
  • 5
  • 30
  • 49
  • 1
    possible duplicate of [Is there a standardized method to swap two variables in Python?](http://stackoverflow.com/questions/14836228/is-there-a-standardized-method-to-swap-two-variables-in-python) – Ffisegydd Apr 03 '14 at 19:47
  • Can you please post a short example of both inputs and expected outputs? – Daniel Apr 03 '14 at 20:07
  • 9
    definitely **not** a duplicate of that other question, because this one here is asking specifically about numpy... – smheidrich Aug 20 '18 at 09:51

2 Answers2

49

I see you're using numpy arrays. In that case, you can also do this:

input_seq[[ix1, ix2]] = input_seq[[ix2, ix1]]
Lewistrick
  • 2,649
  • 6
  • 31
  • 42
33

You can use tuple unpacking. Tuple unpacking allows you to avoid the use of a temporary variable in your code (in actual fact I believe the Python code itself uses a temp variable behind the scenes but it's at a much lower level and so is much faster).

input_seq[ix1], input_seq[ix2] = input_seq[ix2], input_seq[ix1]

I have flagged this question as a duplicate, the answer in the dupe post has a lot more detail.

Community
  • 1
  • 1
Ffisegydd
  • 51,807
  • 15
  • 147
  • 125
  • 15
    This does not seem safe on NumPy arrays. Try: A = np.ones((2,2)); A[1,:] += 1; A[0,:], A[1,:] = A[1,:], A[0,:]; `A` now has 2s all over. – Thomas Arildsen Feb 27 '18 at 19:47
  • 15
    The answer by @lewistrick will work on numpy arrays of arbitrary dimension. This answer will fail on dimension 2 or higher. – Joel Mar 28 '18 at 11:28
  • 1
    This may work for single values (answering the question in the strictest sense), but not groups of values. Try `a=np.array([1,2,3]); b=np.array([4,5,6,7]); a[0:3], b[0:3] = b[0:3], a[0:3]`. The result will be that the first 3 values in b get moved to a, but the a values don't copy into b. This is likely due to passing pointers (i.e. a gets overwritten by b values and THEN copied into b). It's what makes this question interesting IMHO. Adding `.copy()` helps, e.g. `a, b[0:3] = (b[0:3]).copy(), a` works. – sh37211 Jan 25 '21 at 01:11