91

Say for instance I have ...

$var1 = "ABC"
$var2 = 123

and under certain conditions I want to swap the two around like so...

$var1 = 123
$var2 = "ABC"

Is there a PHP function for doing this rather than having to create a 3rd variable to hold one of the values then redefining each, like so...

$var3 = $var1
$var1 = $var2
$var2 = $var3

For such a simple task its probably quicker using a 3rd variable anyway and I could always create my own function if I really wanted to. Just wondered if something like that exists?

Update: Using a 3rd variable or wrapping it in a function is the best solution. It's clean and simple. I asked the question more out of curiosity and the answer chosen was kind of 'the next best alternative'. Just use a 3rd variable.

Taylor
  • 1,700
  • 4
  • 17
  • 18
  • 4
    You can use xor too, like... `b = a xor b`, `a = a xor b`, `b = a xor b` should do the trick... Dunno if theres a function, I'm not good with PHP. – alternative Aug 22 '10 at 14:07
  • 3
    These answers resemble some sort of an obfuscation contest. – Gherman Sep 18 '14 at 07:00

20 Answers20

133

TL;DR

There isn't a built-in function. Use swap3() as mentioned below.

Summary

As many mentioned, there are multiple ways to do this, most noticable are these 4 methods:

function swap1(&$x, &$y) {
    // Warning: works correctly with numbers ONLY!
    $x ^= $y ^= $x ^= $y;
}
function swap2(&$x, &$y) {
    list($x,$y) = array($y, $x);
}
function swap3(&$x, &$y) {
    $tmp=$x;
    $x=$y;
    $y=$tmp;
}
function swap4(&$x, &$y) {
    extract(array('x' => $y, 'y' => $x));
}

I tested the 4 methods under a for-loop of 1000 iterations, to find the fastest of them:

  • swap1() = scored approximate average of 0.19 seconds.
  • swap2() = scored approximate average of 0.42 seconds.
  • swap3() = scored approximate average of 0.16 seconds. Winner!
  • swap4() = scored approximate average of 0.73 seconds.

And for readability, I find swap3() is better than the other functions.

Note

  • swap2() and swap4() are always slower than the other ones because of the function call.
  • swap1() and swap3() both performance speed are very similar, but most of the time swap3() is slightly faster.
  • Warning: swap1() works only with numbers!
evilReiko
  • 19,501
  • 24
  • 86
  • 102
  • 3
    Changed the answer to this one since the question seems to get a lot of attention and you've bench marked them. swap3 is basically the same as the original question wrapped up in function. Proof that simplicity is often better, even if it means extra lines! – Taylor Nov 24 '14 at 18:42
  • 2
    Yep, I upvote your summary too. But you can remove `swap1`, it does some real bulshit. – Alain Tiemblo Jan 11 '15 at 21:08
  • 1
    Swap2 is clearly best for readability/writability. Swap1 is just presumptuous and Swap3 is the 'non swapping' way to do it. Obviously any option is okay if you make your own wrapper function that works how you want, as `swap(&$a,&$b)` can be useful. – Deji Apr 05 '16 at 13:28
  • Swap1 was perfect for me as all I wanted was to swap bytes if one was bigger than the other – Steve Byrne Jun 03 '18 at 09:27
  • @StevenByrne Note that swap1 only works with numbers! – evilReiko Jun 03 '18 at 11:29
  • Yes, which was perfect for my use (number of bits (ints) needing to be swapped) – Steve Byrne Jun 03 '18 at 22:12
  • Why not remove swap1 if it works only with numbers? It's such a big caveat and this function has no advantage over just swapping as in swap3 – laurent Dec 05 '18 at 15:39
  • There is another one way extract(array('a'=>$b,'b'=>$a)); Please add benchmark for it. – Alexey Muravyov Mar 21 '19 at 11:39
  • @AlexeyMuravyov Thank you. Included it. – evilReiko Mar 21 '19 at 12:10
  • 2
    for what it's worth `swap2()` can now be rewritten per [@Pawel Dubiel's answer below](https://stackoverflow.com/a/39692850/1767412) and is ***much*** faster than it was when those benchmarks were written. I ran some benchmarks of my own and over 1 million iterations it only took 0.01 seconds longer than `swap3()` which is of course negligible. Also, `[$a, $b] = [$b, $a];` looks great. – But those new buttons though.. Jan 08 '20 at 18:13
99

There's no function I know of, but there is a one-liner courtesy of Pete Graham:

list($a,$b) = array($b,$a);

not sure whether I like this from a maintenance perspective, though, as it's not really intuitive to understand.

Also, as @Paul Dixon points out, it is not very efficient, and is costlier than using a temporary variable. Possibly of note in a very big loop.

However, a situation where this is necessary smells a bit wrong to me, anyway. If you want to discuss it: What do you need this for?

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • 3
    +1 - found the same, and agree, not sure I like it either - using a temp variable is considerably better - as is writing your own swap method if you find yourself doing this often. – Will A Aug 22 '10 at 14:01
  • +1, Beat me to it as well :) I like the idea in principle, but unfortunately the PHP syntax just leaves a bad taste... – Justin Ethier Aug 22 '10 at 14:03
  • wow, super quick response. I take my hat off to all of you! is a nice little trick that. – Taylor Aug 22 '10 at 14:05
  • @Taylor there is also a question to you in this quick response. – Your Common Sense Aug 22 '10 at 14:09
  • using it to switch 2 values in a field if some plonker puts values in the form around the wrong way. The values are fairly restricted to what they can be so its easy enough to figure out whether they should have been around the other way. More of a usability thing so it helps out those that aren't great on a computer... or just having a bad moment. :-) – Taylor Aug 22 '10 at 14:17
  • 28
    as this is the accepted answer for a question that might educate others, it's worth pointing out just how inefficient this is. You're asking PHP to create an array, only to immediately discard it. I benchmarked this approach against using a temporary variable, and found that using a temp variable is over 7 times faster. I would also argue it makes the intent clearer too, as it's a common idiom! – Paul Dixon Aug 22 '10 at 14:55
  • @Paul great information about the benchmark - it's meaningless for one or two operations, but will make a difference in loops. Editing the answer to reflect that. – Pekka Aug 22 '10 at 14:58
  • @paul figured as much, simplicity usually is. Good to see an actual benchmark. – Taylor Aug 24 '10 at 05:54
  • 2
    And since this answerer is sceptical, what made me Google whether PHP had a built-in `swap()` is iterating through an array where the keys hold value - e.g. they indicate columns in a database, and the values indicate values. However if there isn't a pair, just a value, then you can have the option to use the value as the key (swap) and use a default value. Since in my example I don't need to keep the key, it's not _really_ essential, but if I did need to keep the array index, I'd rather use a (bult-in) `swap()` call than creating a stupidly named temporary. But, this isn't built-in... – Deji Apr 05 '16 at 13:34
  • Link in answer is dead - *404 File not found*. – Pang Feb 28 '17 at 03:09
  • It's also worth noted that you can swap more than 2 variables with this code snippet: `$x = 'x'; $y = 'y'; $z = 'z'; list($x, $y, $z) = [$y, $z, $x];` will return `$x = 'y'; $y = 'z'; $z = 'x';`. Useful for stack ordering, if you don't already have an array for this :-) – Yvan Aug 23 '17 at 08:55
74

Yes, there now exists something like that. It's not a function but a language construct (available since PHP 7.1). It allows this short syntax:

 [$a, $b] = [$b, $a];

See "Square bracket syntax for array destructuring assignment" for more details.

trincot
  • 317,000
  • 35
  • 244
  • 286
Pawel Dubiel
  • 18,665
  • 3
  • 40
  • 58
  • 4
    My vote is for this one because: It is easily done _inline_, and it is only _one line_ (I did not test to see if it runs faster than the function call options.) My programming time is usually more valuable than the computer time. – Rick James Dec 15 '20 at 21:14
  • My vote for this too – Ryan NZ Sep 18 '21 at 10:17
  • 1
    This is essentially the same as swap2() in the accepted answer, ie list($x, $y) = array($y, $x); – oomp Mar 22 '22 at 03:08
  • 1
    @oomp I agree but language construct wins over functions call. – Ahsaan Yousuf Oct 13 '22 at 01:46
  • @AhsaanYousuf https://www.php.net/list "Like array(), this is not really a function, but a language construct. " – chx Apr 22 '23 at 22:56
17

It is also possible to use the old XOR trick ( However it works only correctly for integers, and it doesn't make code easier to read.. )

$a ^= $b ^= $a ^= $b;
Pawel Dubiel
  • 18,665
  • 3
  • 40
  • 58
  • 3
    If you use it with words, containing same parts, it returns funny and unexpected result: http://ideone.com/NGQVYH – Ilia Ross Nov 10 '13 at 17:50
10

Yes, try this:

// Test variables
$a = "content a";
$b = "content b";

// Swap $a and $b
list($a, $b) = array($b, $a);

This reminds me of python, where syntax like this is perfectly valid:

a, b = b, a

It's a shame you can't just do the above in PHP...

Justin Ethier
  • 131,333
  • 52
  • 229
  • 284
7

Another way:

$a = $b + $a - ($b = $a);
Prasanth
  • 5,230
  • 2
  • 29
  • 61
7

For numbers:

$a = $a+$b;
$b = $a-$b;
$a = $a-$b;

Working:

Let $a = 10, $b = 20.

$a = $a+$b (now, $a = 30, $b = 20)

$b = $a-$b (now, $a = 30, $b = 10)

$a = $a-$b (now, $a = 20, $b = 10 SWAPPED!)

5
list($var1,$var2) = array($var2,$var1);
Thomas Clayson
  • 29,657
  • 26
  • 147
  • 224
4

This one is faster and needs lesser memory.

function swap(&$a, &$b) {
    $a = $a ^ $b;
    $b = $a ^ $b;
    $a = $a ^ $b;
}

$a = "One - 1";
$b = "Two - 2";

echo $a . $b; // One - 1Two - 2

swap($a, $b);

echo $a . $b; // Two - 2One - 1

Working example: http://codepad.viper-7.com/ytAIR4

Ron van der Heijden
  • 14,803
  • 7
  • 58
  • 82
  • 1
    A note to all: this function only works properly in all cases if `$a` and `$b` are the same length, as per @m13r – Lux Jul 12 '17 at 19:18
4

another simple method

$a=122;
$b=343;

extract(array('a'=>$b,'b'=>$a));

echo '$a='.$a.PHP_EOL;
echo '$b='.$b;
user2907171
  • 315
  • 1
  • 7
2

Here is another way without using a temp or a third variable.

<?php
$a = "One - 1";
$b = "Two - 2";

list($b, $a) = array($a, $b);

echo $a . $b;
?>

And if you want to make it a function:

    <?php
    function swapValues(&$a, &$b) {
         list($b, $a) = array($a, $b);
     }
    $a = 10;
    $b = 20;
    swapValues($a, $b);

    echo $a;
    echo '<br>';
    echo $b;
    ?>
GIPSSTAR
  • 2,050
  • 1
  • 25
  • 20
2

Thanks for the help. I've made this into a PHP function swap()

function swap(&$var1, &$var2) {
    $tmp = $var1;
    $var1 = $var2;
    $var2 = $tmp;
}

Code example can be found at:

http://liljosh.com/swap-php-variables/

Josh LaMar
  • 199
  • 3
  • 8
2

3 options:

$x ^= $y ^= $x ^= $y; //bitwise operators

or:

list($x,$y) = array($y,$x);

or:

$tmp=$x; $x=$y; $y=$tmp;

I think that the first option is the fastest and needs lesser memory, but it doesn’t works well with all types of variables. (example: works well only for strings with the same length)
Anyway, this method is much better than the arithmetic method, from any angle.
(Arithmetic: {$a=($a+$b)-$a; $b=($a+$b)-$b;} problem of MaxInt, and more...)

Functions for example:

function swap(&$x,&$y) { $x ^= $y ^= $x ^= $y; }
function swap(&$x,&$y) { list($x,$y) = array($y,$x); }
function swap(&$x,&$y) { $tmp=$x; $x=$y; $y=$tmp; }

//usage:
swap($x,$y);
Dani-Br
  • 2,289
  • 5
  • 25
  • 32
0

If both variables are integers you can use mathematical approach:

$a = 7; $b = 10; $a = $a + $b; $b = $a - $b; $a = $a - $b;

Good blog post - http://booleandreams.wordpress.com/2008/07/30/how-to-swap-values-of-two-variables-without-using-a-third-variable/

-1

Yes I know there are lots of solutions available, but here is another one. You can use parse_str() function too. Reference W3Schools PHP parse_str() function.

<?php
    $a = 10;
    $b = 'String';

    echo '$a is '.$a;
    echo '....';
    echo '$b is '.$b;

    parse_str("a=$b&b=$a");

    echo '....After Using Parse Str....';

    echo '$a is '.$a;
    echo '....';
    echo '$b is '.$b;

?>

DEMO

Vidhyut Pandya
  • 1,605
  • 1
  • 14
  • 27
  • 1
    Why the hell would you do that ... and what about the case, when $b contains something like `b&a=abc`? – jirig Oct 01 '17 at 11:20
-1

I checked all solutions after that i came up with another solution that was not found anywhere. my logic is simple. i used PHP variable ref. pattern. means $$. you can read more about this by this link https://www.php.net/manual/en/language.variables.variable.php

$a =12;$b="ABC";
$$a =$b;
$$b= $$a.$a;
echo " a = $a and b=$b <br>now after reverse.<br>";
echo $$b;

//output : abc12

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
pankaj
  • 1
  • 17
  • 36
  • 1
    This code makes no sense – Your Common Sense Jun 16 '22 at 18:50
  • Although working and interesting - I didn't know about Variable Variables until reading this, although now I wish I never found out about them - the code is impractical and there's no benefit over simply using a variable called `$temp` :) – Tony Jun 22 '23 at 21:46
-2
$a = 'ravi';

$b = 'bhavin';

$a = $b.$a;

$b = substr($a,strlen($b),strlen($a));

$a = substr($a,0,strlen($a)-strlen($b));

echo "a=".$a.'<br/>'.'b='.$b;
n00dl3
  • 21,213
  • 7
  • 66
  • 76
Bhavin Thummar
  • 1,255
  • 1
  • 12
  • 29
-3
<?php

swap(50, 100);

function swap($a, $b) 
{
   $a = $a+$b;
   $b = $a - $b;
   $a = $a - $b;
   echo "A:". $a;
   echo "B:". $b;
 }
?>
Sham Haramalkar
  • 117
  • 1
  • 3
  • 1
    While answers are always appreciated, this question was asked 6 **years** ago, and already had an accepted solution. Please try to avoid 'bumping' questions to the top by providing answers to them, unless the question was not already marked as resolved, or you found a new and improved solution to the problem. Also remember to provide some [**context surrounding your code**](https://meta.stackexchange.com/questions/114762) to help explain it. Check out the documentation on [**writing great answers**](http://stackoverflow.com/help/how-to-answer) for some tips on how to make your answers count :) – Obsidian Age Aug 01 '17 at 00:33
-4

another answer

$a = $a*$b;
$b = $a/$b;
$a = $a/$b;
shaggy
  • 205
  • 3
  • 5
-11
$a=5; $b=10; $a=($a+$b)-$a; $b=($a+$b)-$b;
Tushar Gupta - curioustushar
  • 58,085
  • 24
  • 103
  • 107