6

Can you swap the values of two variables without using a third variable as a temporary placeholder?

0

5 Answers 5

32

The canonical way to swap two variables in Python is

a, b = b, a

Please note than this is valid whatever the "type" of a or b is (numeric, string, tuple, object, ...). Of course, it works too if both variables reference values of different types.


As many imperative languages, Python evaluates assignments right to left. Conceptually all behave like if a tuple was build for the right hand part of the expression, and then deconstructed to perform the affectation to the left hand part. This has already been explained more clearly than I can here: https://stackoverflow.com/a/14836456/2363712

The real details are implementation dependent though. For example, to build on a comment by @undefined is not a function below, the CPython virtual machine has a ROT_TWO opcode that swap the two top-level items on the stack, and so allow to optimize such affectation. See this previous answer for a detailed explanation: https://stackoverflow.com/a/21047622/2363712

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

7 Comments

Internally this may use an extra location on the stack though. There is a way to get Python's bytecode(?) instructions to find this out but I don't know this off the top of my head ...
@Brendan Implementation detail? ;) More seriously, you probably have right. But as I understand the question this is really without using a third Python variable, not "an intermediate memory location".
A tuple is not created when we swap just 2 variables, instead ROT_TWO is used.
I think you should probably replace the link in your answer with this great answer from Martijn.
"As many imperative languages, Python evaluate right to left" - no, it's almost always left to right. Assignment is just a weird special case.
|
8

This is the main snippet of code:

 x = 10
 y = 5

 x = x + y;  // x now becomes 15
 y = x - y;  // y becomes 10
 x = x - y;  // x becomes 5

This is what your friend meant.

1 Comment

x = 15 y =5 ; x = 15 + 5 =20 ; y =20-15 = 5; y value is 5 now. x = 20-5 =15;
4

If your friend is a "math-snob", he may have in mind a particular trick, which you can use in languages where you can apply the XOR function to the bitstring representation of numbers.

Say we have variables X and Y, with starting values of a and b respectively. Perform the following assignments (the values of the variables which result are shown as comments):

(start)      # X == a; Y == b
X = X XOR Y  # X == a XOR b;  Y == b
Y = X XOR Y  # X == a XOR b;  Y == b XOR (a XOR b)
X = X XOR Y  # X == (a XOR b) XOR b XOR (a XOR b);  Y == b XOR (a XOR b)

Because XOR is associative, we can regroup the resulting equations as follows:

X == (a XOR a) XOR (b XOR b) XOR b
Y == (b XOR b) XOR a

Because x XOR x == 0 and x XOR 0 == x, we can simply remove all those pairs of variables XOR'ed with themselves, and what's left is:

X == b
Y == a

which is what we wanted, to switch the values without using a third variable.

It's been quite a while since I did any bit manipulation in Python, so I cannot tell you whether this trick works in Python, but there are languages where it works. I also can't tell you whether it actually has sufficient benefits to balance out its non-obviousness.

3 Comments

Actually, you're right. At the time my friend could not remember what it was. She could remember the problem but not the name of the solution. I stumbled across XOR recently and ask her about it; she confirmed.
Actually, my hopes with initial share were intended to be a building block to a larger conversation terminating with a language-agnostic answer; those hopes died almost immediately. My example just happened to be in python. That's just where I was at the time. As far as I'm concerned @afeldspar provided the right answer.
2

You can directly try for:

a, b = b, a

It is a canonical way to exchange the value without using a third variable.

Comments

-6

A seemingly simple question. In retrospect, presumably designed to determine whether or not you think mathematically. I pondered, it's not a simple problem but not out of reach.

As research reveals this is a fairly common question with many good and bad answers. I believe I've found an illustrative solution:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# MODULES


# VARIABLES
x = 20
y = 10


# FUNCTIONS
# Swap 2 vars: longhand method, the portable way:
def swapNosL(val1, val2):
    print("BEFOR: val1: %r,  val2: %r") % (val1, val2)
    val1 = val1 + val2
    val2 = val1 - val2
    val1 = val1 - val2
    print("AFTER: val1: %r,  val2: %r") % (val1, val2)
    return(val1, val2)


# Swap 2 vars: shorthand method, the non/less-portable way:
def swapNosC(val1, val2):
    print("BEFOR: val1: %r and val2: %r") % (val1, val2)
    val1, val2 = val2, val1
    print("AFTER: val1: %r and val2: %r") % (val1, val2)
    return(val1, val2)


# MAIN PROGRAM
print("")
print("The Problem:")
print("We need to swap 2 variables without using a 3rd.")
print("The values: 'x' is %r and 'y' is %r.") % (x, y)
print("")

(retVal1, retVal2) = swapNosC(x, y)
print("")
print("Now values: 'x' is %r and 'y' is %r.") % (retVal1, retVal2)

print"\n"

While there is some unnecessary repetition, the logic is solid. To baseline:

1) It works with all integers both positive and negative; I haven't tested floats yet.

2) The same memory is used 1 way or the other; only 2 variables are used either way.

3) Portability is (or should) always be a goal. In the case that programming languages go away and you need to port to a new one, research indicates that handling this problem mathematically will allow for greater portability.

In the "bad" example, this method is language-specific and porting to a language would (some day) require a different solution. I hope Python never goes the way of COBOL but the future is a big place.

However, in the "good" example the math is handled in a similar way in the C language. In fact, research also indicates math is generally handled the same way in most languages.

Therefore leaving the math in tact and only negotiating the syntax modification is the more portable method.

At some point I will concede to my friend that this was a good learning opportunity for me. But not for a while. I found the answer but failed by cheating with research.

TT

35 Comments

But this would only work on numeric variables, correct?
Could you explain why left, right = right, left is considered a "bad answer"? As I understand, the question is "Python oriented" -- so why not use the language idioms to solve problems.
Honestly, the first method you posted is a terrible way of implementing swap in Python. It will fail silently on many floating point values, and it won't work at all for non-numeric types.
@todd_dsm if it's only one or two lines of code, and it's risky and suboptimal in both languages, then I would not be that worried about portability. When I think portability concerns, I think things like "will these signals work correctly on Windows?" not "how can I change this variable swap to C while changing as few characters as possible?"
You yourself said that you wanted to swap floating point numbers, but your solution doesn't even do that properly. For example, arguments 0.0000001 and 1000000 gives incorrect output. And I'm not really sure why you mentioned strings; it definitely doesn't work with them (they don't have a subtraction operator defined).
|

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.