Prohození prvků

Školení, která pořádám

Pokud potřebujeme prohodit hodnotu dvou prvků, lze to řešit přes pomocnou proměnnou:

<?php
$pom = $a;
$a = $b;
$b = $pom;
?>

Elegantnější mi nicméně přijde pro tuto operaci použít konstrukci list, která do svých parametrů přiřadí prvky z pole na pravé straně přiřazení:

<?php
list($a, $b) = array($b, $a);
?>
Jakub Vrána, Výuka, 27.9.2006, diskuse: 21 (nové: 0)

Diskuse

Michalek:

Zajímavý, logický, ale samotnýho by mě to nenapadlo... Dík moc, hodí se.

ikona dgx:

Praví, drsní a assemblerem ošlehaní hackeři používají výhradně:
<?php
$a
^= $b;
$b ^= $a;
$a ^= $b;
?>
(funguje pro celá čísla a stejně dlouhé řetězce) :-)

tracy:

Kdepak. Pravý, drsný a assemblerem ošlehaný hacker by použil:
<?php
$a
^= $b ^= $a ^= $b;
?>

ikona dgx:

:-)) Ten zápis má dokonce i estetické přednosti.

Jinak ti nejošlehanější píšou zásadně v bytecode:
FETCH_R        $3, 'b'
FETCH_RW       $2, 'a'
ASSIGN_BW_XOR  $4, $2, $3
FETCH_RW       $1, 'b'
ASSIGN_BW_XOR  $5, $1, $4
FETCH_RW       $0, 'a'
ASSIGN_BW_XOR  $0, $5

Pavel:

A Ti nej nej borci si to nechají naprogramovat :)

Llaik:

nene, ti nejvetsi borci chodi na php.vrana.cz a prectou si hotova reseni :)

RATMex B:

Áno, bežne sa to používalo ako macro, pretože na úrovni JSI sa s ničím iným, ako "sledom bitov", nepracovalo a sprehľadňoval sa tým kód.
Lenže v PHP sú okrem integeru (a booleanu) aj ďalšie typy, s ktorými to fungovať nebude.

johno:

Alebo si spraviť funkciu function swap(&$a, &$b) { $tmp = $a; $a = $b; $b = $tmp; }

Juro Hajdúch:

a aby som sa zbavil $tmp:
<?php
function swap(&$a, &$b) { list($a, $b) = array($b, $a); }
?>

ikona dgx:

Řešení pomocí list() je o 80% pomalejší!

(to je prostě parádní odborná pitva nejbanálnějšího programátorského úkonu, který se navíc skoro nikdy nepoužívá :-))

v6ak:

ona se tam jakože nepoužívá pomocná proměnná, ale ve skutečnosti jo.

PIF:

aspoň jsme se zase sterilně zasmáli :) každopádně krása se tomu upřít nedá.

ikona MiSHAK:

Wow!

Ondra:

V patek jsme to resili v algortmizaci (co porada nas gympl), byl jsem uspesnym resitelem s timto kodem:

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

Pisu to z hlavy tak ze mne laskave po(o)pravte jestli je to spatne. To mi prijde nejelegantnejsi reseni, bez zadnych binarnich operaci, bez jinych funkci.

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL: Reakce na: Ondra

Fak:

ale co řetězce?

Squad_Leader:

Už to nehulte :-D  Nedělá vám to dobře.

v2j:

re: {$tmp = $a; $a = $b; $b = $tmp;}

Trochu problém bych viděl v tom, že v momentě, kdy se změní reference $a, PHP vytvoří pro $tmp klon prvku, což by mohlo vadit. Třeba v prohazování polí, kdy se naprosto zbytečně vytváří paměťová kopie celého pole a naopak originál zruší. Náročný na paměť i čas.

Uvažuju správně? Ale stejně nejlepší řešení bude přes list(), přesně to jsem hledal ;-)

ikona v6ak:

// Snad ten workaround s Operou mini pojede.
Pokud proměnné a a b jsou objekty, pak ve starém PHP4 dojde ke klonování objektu (vpodstatě kopírování, nevím, jak to je s vnitřními vlastnostmi), ale v PHP5 pouze ke kopírování odkazů (teď si nejsem jist, jestli to je zde správný termín).

ikona v6ak:

Tak ještě drobné OT: Pokud v Opeře mini před vložením příspěvku reloadnu (#0) a pak teprve stisknu reagovat, pak reakce fungují dobře.

ikona Jakub Vrána OpenID:

Vzhledem k tomu, že PHP používá copy-on-write, tak přiřazení libovolně velké proměnné je operace s konstantním časem.

ikona v6ak:

To je vlastně taky pravda. Já to bral jen z logiky php programátora.
Dodám odkazy:
* http://latrine.dgx.cz/php-puvab-optimalizace-rychlosti
* http://latrine.dgx.cz/php-cerna-magie-optimalizace
avatar © 2005-2019 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.