Чи існує функція PHP для обміну значеннями двох змінних?


77

Скажімо, наприклад, я маю ...

$var1 = "ABC"
$var2 = 123

і за певних умов я хочу поміняти їх обома так ...

$var1 = 123
$var2 = "ABC"

Чи існує функція PHP для цього, а не для створення третьої змінної, щоб утримувати одне зі значень, а потім перевизначити кожне, так ...

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

Для такого простого завдання його, мабуть, швидше використовувати 3-ю змінну, і я завжди міг би створити власну функцію, якщо б дуже хотів. Просто цікавився, чи існує щось подібне?

Оновлення: найкращим рішенням є використання третьої змінної або обернення її у функцію. Це чисто і просто. Я поставив це питання більше з цікавості, і обрана відповідь була якось „наступною найкращою альтернативою“. Просто використовуйте 3-ю змінну.


4
Ви можете використовувати XOR теж, як ... b = a xor b, a = a xor b, b = a xor bслід зробити трюк ... Незнайка якщо Theres функції, я не дуже добре з PHP.
альтернатива

3
Ці відповіді нагадують якесь змагання за затуманення.
Герман,

Відповіді:


110

TL; DR

Немає вбудованої функції. Використовуйте, swap3()як зазначено нижче.

Резюме

Як багато хто згадував, існує кілька способів зробити це, найбільш помітними є ці 4 методи:

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));
}

Я протестував 4 методи в циклі for з 1000 ітерацій, щоб знайти найшвидший з них:

  • swap1()= наведене приблизне середнє значення 0,19 секунди.
  • swap2()= набране приблизне середнє значення 0,42 секунди.
  • swap3()= набране приблизне середнє значення 0,16 секунди. Переможець!
  • swap4()= набране приблизно середнє значення 0,73 секунди.

А для читабельності я вважаю, що swap3()це краще, ніж інші функції.

Примітка

  • swap2()і swap4()завжди повільніші за інші через виклик функції.
  • swap1()і swap3()швидкість роботи обох дуже схожа, але більшу частину часу swap3()трохи швидше.
  • Увага: swap1() працює лише з цифрами!

3
Відповідь на це змінено, оскільки питання, схоже, привертає багато уваги, і ви вже позначили їх. swap3 - це в основному те саме, що оригінальне запитання, завершене функцією. Доказ того, що простота часто краща, навіть якщо це означає додаткові рядки!
Тейлор,

2
Так, я також підтримую ваш резюме. Але ви можете видалити swap1, це робить справжню фігню.
Ален Тіембло

1
Swap2, очевидно, найкращий для читабельності / запису. Swap1 - це просто самовпевнено, а Swap3 - це „не обмінний” спосіб зробити це. Очевидно, що будь-який варіант є нормальним, якщо ви створюєте власну функцію обгортки, яка працює так, як ви хочете, як це swap(&$a,&$b)може бути корисно.
Дедзі

Swap1 був ідеальним для мене, оскільки все, що я хотів, було поміняти місцями байти, якщо один був більший за інший
Стів Берн

1
адже те, що воно варте, swap2()тепер можна переписати відповідно до відповіді @Pawel Dubiel нижче і набагато швидше, ніж це було, коли були написані ці тести. Я провів деякі власні тести, і понад 1 мільйон ітерацій зайняв лише 0,01 секунди довше, ніж swap3()це, звичайно, незначно. Крім того, [$a, $b] = [$b, $a];виглядає чудово.
billynoah

87

Я не знаю жодної функції, але є одностороння ввічливість Піта Грехема :

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

не впевнений, чи подобається мені це з точки зору технічного обслуговування, однак, оскільки це насправді не інтуїтивно зрозуміти.

Крім того, як зазначає @Paul Dixon, це не надто ефективно і є дорожчим, ніж використання тимчасової змінної. Можливо, зверніть увагу на дуже великий цикл.

Однак ситуація, коли це необхідно, мені все одно пахне трохи неправильно. Якщо ви хочете це обговорити: Для чого вам це потрібно?


3
+1 - знайшов те саме, і погодьтеся, не впевнений, що мені це теж подобається - використання змінної temp набагато краще - як і написання власного методу підкачки, якщо ви часто робите це.
Буде

+1, побийте мене також :) Ідея мені подобається в принципі, але, на жаль, синтаксис PHP просто залишає неприємний смак ...
Джастін Етьє

вау, супер швидка реакція. Я знімаю шапку всім вам! це приємний маленький фокус, який.
Тейлор,

28
оскільки це прийнята відповідь на запитання, яке може навчити інших, варто вказати, наскільки це неефективно. Ви просите PHP створити масив, лише щоб негайно його відкинути. Я порівняв цей підхід із використанням тимчасової змінної та виявив, що використання змінної temp відбувається в 7 разів швидше. Я б також стверджував, що це також робить намір зрозумілішим, оскільки це загальноприйнята ідіома!
Пол Діксон,

2
І оскільки цей відповідач скептично налаштований, то, що змусило мене погуглити, чи був PHP вбудованим, swap()це ітерація через масив, де ключі містять значення - наприклад, вони вказують стовпці в базі даних, а значення вказують значення. Однак, якщо немає пари, а лише значення, тоді ви можете мати можливість використовувати значення як ключ (своп) і використовувати значення за замовчуванням. Оскільки в моєму прикладі мені не потрібно зберігати ключ, це насправді не є суттєвим, але якщо мені потрібно було зберегти індекс масиву, я скоріше використовую виклик (bult-in), swap()ніж створюю тупо іменований тимчасовий. Але це не вбудовано ...
Дедзі,

45

Так, зараз існує щось подібне. Це не функція, а мовна конструкція (доступна з PHP 7.1). Це дозволяє такий короткий синтаксис:

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

Докладніше див. У "Синтаксисі квадратних дужок для призначення деструктуризації масиву" .


Я голосую за цей, оскільки: Це легко зробити вбудовано , і це лише один рядок (я не перевіряв, чи працює він швидше, ніж параметри виклику функції.) Мій час програмування, як правило, цінніший за комп’ютерний.
Рік Джеймс,

16

Також можна використовувати старий фокус XOR (однак він працює тільки правильно для цілих чисел і не полегшує читання коду ..)

$a ^= $b ^= $a ^= $b;

2
Якщо використовувати його зі словами, що містять однакові частини, це поверне смішний і несподіваний результат: ideone.com/NGQVYH
Ілля Ростовцев

9

Так, спробуйте це :

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

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

Це нагадує мені python, де такий синтаксис цілком справедливий:

a, b = b, a

Шкода, що ви не можете просто зробити вищезазначене в PHP ...



7

Для номерів:

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

Робоча:

Нехай $ a = 10, $ b = 20.

$ a = $ a + $ b (зараз $ a = 30, $ b = 20)

$ b = $ a- $ b (зараз $ a = 30, $ b = 10)

$ a = $ a- $ b (зараз $ a = 20, $ b = 10 ЗАМІНЕНО!)


Це працює лише для чисел і не є вбудованою PHP-функцією. ОП вимагало більш загального підходу та заздалегідь визначеної функції.
keenthinker

Ви маєте рацію, пропустили це, дивлячись на всі інші відповіді та реалізації.
Naga Krishna Teja Komma

Хоча відповідь на запитання не правильна, я радий, що хтось згадав про цей підхід, тож підтримайте мене :)
Арман П.

Якщо ваші цифри занадто великі, цей метод може переповнитися.
Рік Джеймс,


4

Цей швидший і потребує менше пам'яті.

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

Робочий приклад: http://codepad.viper-7.com/ytAIR4


1
Примітка для всіх: ця функція працює належним чином лише у всіх випадках, якщо $aі $bоднакової довжини, як @ m13r
Електра


2

Ось інший спосіб без використання тимчасової або третьої змінної.

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

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

echo $a . $b;
?>

І якщо ви хочете зробити це функцією:

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

    echo $a;
    echo '<br>';
    echo $b;
    ?>


2

3 варіанти:

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

або:

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

або:

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

Я думаю, що перший варіант є найшвидшим і потребує меншої пам’яті, але він погано працює з усіма типами змінних. (приклад: добре працює лише для рядків з однаковою довжиною)
У будь-якому випадку, цей метод набагато кращий за арифметичний з будь-якого кута.
(Арифметика: {$ a = ($ a + $ b) - $ a; $ b = ($ a + $ b) - $ b;} проблема MaxInt та багато іншого ...)

Функції, наприклад:

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);

Це працює (якщо вони мають однакову довжину). Перевірено зараз, на PHP5.5
Dani-Br,

код: функція обміну (& $ x, & $ y) {$ x ^ = $ y ^ = $ x ^ = $ y;} $ a = "aaa"; $ b = "bbb"; обмін ($ a, $ b); echo $ a, $ b;
Дані-Бр

1

Так, я знаю, що існує безліч рішень, але ось ще одне. Ви також можете використовувати parse_str()функцію. Посилання на функцію parse_str () W3Schools PHP .

<?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;

?>

ДЕМО


Чому б ти це зробив ... і як щодо випадку, коли $ b містить щось подібне b&a=abc?
jirigracik



-1
<?php

swap(50, 100);

function swap($a, $b) 
{
   $a = $a+$b;
   $b = $a - $b;
   $a = $a - $b;
   echo "A:". $a;
   echo "B:". $b;
 }
?>

1
Хоча відповіді завжди цінуються, це питання було задано 6 років тому і вже мало прийняте рішення. Будь ласка, намагайтеся уникати "натрапляння" запитань на вершину, надаючи відповіді на них, якщо питання ще не було позначено як вирішене, або ви знайшли нове та вдосконалене рішення проблеми. Також не забудьте надати контекст навколо вашого коду, який допоможе пояснити його. Ознайомтеся з документацією щодо написання чудових відповідей, щоб отримати кілька порад щодо того, як
Obsidian Age


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.