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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.