38

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
3
  • 1
    possible duplicate of Is there a standardized method to swap two variables in Python? Commented Apr 3, 2014 at 19:47
  • Can you please post a short example of both inputs and expected outputs? Commented Apr 3, 2014 at 20:07
  • 10
    definitely not a duplicate of that other question, because this one here is asking specifically about numpy... Commented Aug 20, 2018 at 9:51

2 Answers 2

59

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

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

To explain this a bit:

input_seq[ix1] = 5 # sets value at index `ix1` to `5`
input_seq[ix2] = 42 # sets value at index `ix2` to `42`

You can also do this:

ixs = [ix1, ix2] # create a list of indices to alter
input_seq[ixs] = [5, 42] # sets the two values simultaneously

To even shorten this further, substituting ixs:

input_seq[[ix1, ix2]] = [5, 42] # sets the two values simultaneously in one line

Now Python has a very nice feature in which you can swap two variables like this without a temporary variable:

a, b = b, a # swap the values of a and b

So if you know you can read two variables by index from the array like this:

input_seq[[ix2, ix1]] # reads two values

You can set them as explained in the top of this comment.

Sign up to request clarification or add additional context in comments.

2 Comments

This would deserve an additional explanation on the double brackets indexing.
You're right. I added an explanation, hope this helps. Happy coding!
35

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.

3 Comments

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.
The answer by @lewistrick will work on numpy arrays of arbitrary dimension. This answer will fail on dimension 2 or higher.
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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.