2010-08-03 9 views
14

Powiel możliwe:
is “else if” faster than “switch() case” ?„jeśli” kontra „przełącznik”

Napotkałem wiele sytuacji, w których ostatnio mam bardzo proste warunkowe i trzeba oddział przepływ aplikacji. W „najprostsze” środki osiągania tego, co robię, to tylko zwykły stary if/elseif stwierdzenie:

if($value == "foo") { 
    // ... 
} elseif($value == "bar") { 
    // ... 
} elseif($value == "asdf" || $value == "qwerty") { 
    // ... 
} 

... ale jestem również biorąc pod uwagę coś takiego:

switch($value) { 
    case "foo": 
     // ... 
     break; 
    case "bar": 
     // ... 
     break; 
    case "qwer": 
    case "asdf": 
     // ... 
} 

Wydaje się to trochę mniej czytelny, ale może jest bardziej wydajny? Jednak, gdy pojawia się coraz więcej „lub” wyrażenia w warunkowej, wydaje się, że oświadczenie przełącznik jest znacznie bardziej czytelne i użyteczne:

switch($value) { 
    case "foo": 
     // ... 
     break; 
    case "bar": 
    case "baz": 
    case "sup": 
     // ... 
     break; 
    case "abc": 
    case "def": 
    case "ghi": 
     // ... 
     break; 
    case "qwer": 
    case "asdf": 
     // ... 
} 

Ja również widziałem opcje gdzie przepływ kodu za pomocą tablic i rozgałęzione funkcje:

function branch_xyz() {/* ... */} 
function branch_abc() {/* ... */} 
function branch_def() {/* ... */} 

$branches = array(
    "xyz"=>"branch_xyz", 
    "abc"=>"branch_abc", 
    "def"=>"branch_def" 
); 
if(isset($branches[$value])) { 
    $fname = $branches[$value]; 
    $fname(); 
} 

Ta ostatnia opcja również przypuszczalnie ma tę zaletę, że jest dystrybuowana w wielu plikach, choć jest dość brzydki.

Które z odczuć mają największe zalety przy najniższych kosztach pod względem wydajności, czytelności i łatwości użytkowania?

+1

Używanie 'switch' jest lepiej w takiej sytuacji masz podane. – Sarfraz

+2

Wydajność nawet nie ma na to wpływu. Najpierw zapisz czytelny kod, a następnie profiluj i zoptymalizuj w razie potrzeby. –

+0

Duplikat duplikatu itp. Http://stackoverflow.com/questions/3387758/java-case-statment-or-if-statement-efficiency-perspective –

Odpowiedz

27

Osobiście uważam, że przełącznik jest bardziej czytelny. Oto powód:

if ($foo == 'bar') { 
} elseif ($foo == 'baz') { 
} elseif ($foo == 'buz') { 
} elseif ($fou == 'haz') { 
} 

Skrócone tak, można łatwo zobaczyć utrącają (czy to literówka, czy uczciwy różnica). Ale z przełącznikiem, wiesz niejawnie, co oznaczało:

switch ($foo) { 
    case 'bar': 
     break; 
    case 'baz': 
     break; 
    case 'buz': 
     break; 
    case 'haz': 
     break; 
} 

Plus, który jest łatwiejszy do czytania:

if ($foo == 'bar' || $foo == 'baz' || $foo == 'bat' || $foo == 'buz') { 
} 

lub

case 'bar': 
case 'baz': 
case 'bat': 
case 'buz': 
    break; 

Z punktu widzenia wydajności ... No , nie przejmuj się wydajnością. Jeśli nie wykonasz kilku tysięcy w ciasnej pętli, nie będziesz nawet w stanie stwierdzić różnicy (różnica prawdopodobnie będzie w zakresie mikro-sekundowym, jeśli nie niższym).

Przejdź do metody, która jest najbardziej czytelna. To jest ważna część. Nie próbuj mikro-optymalizacji. Pamiętaj, Premature Optimization Is The Root Of All Evil ...

+1

Należy uważać, aby przełącznik dał ** fałszywe ** negatywne i fałszywie dodatnie z powodu [luźne porównanie] (http://stackoverflow.com/q/3525614/632951). Tutaj, 'przełącznik' jest zapachem kodu i bezpieczeństwem ipso facto. Zamiast tego użyj kluczy tablicowych. – Pacerier

+0

@Pacerier, dlaczego przełącznik jest zmorą bezpieczeństwa? –

+3

@ ryabenko-pro, luźne porównanie da ci subtelne błędy: 'switch (0) {case null: echo 'null'; przerwa; default: echo 'not null';} ' – Pacerier

1

Przełącznik informuje przyszłych czytelników, że rozgałęziają się w oparciu o wartość jednej wartości, które musieliby zakładać inaczej, patrząc na wszystkie warunki. Więc wolałbym przełącznik dla jasności

44

Wiem, mikro-optymalizacja jest zła.Ale ciekaw jestem, zrobiłem trochę odniesienia za pomocą tego skryptu:

<?php 
$numof = 100000; 
$file = fopen('benchmark.php', 'w'); 
if (!$file) die('file error'); 
fwrite($file, '<pre><?php' . "\n" . 'echo $i = $_GET[\'i\'], "\n";' . "\n"); 

fwrite($file, 
'$start = microtime(true); 
if ($i == 0) {}' . "\n"); 
for ($i = 1; $i < $numof; ++$i) { 
    fwrite($file, 'elseif($i == '.$i.') {}'. "\n"); 
} 
fwrite($file, 
'echo \'elseif took: \', microtime(true) - $start, "\n";' . "\n"); 

fwrite($file, 
'$start = microtime(true); 
switch($i) {' . "\n"); 
for ($i = 1; $i < $numof; ++$i) { 
    fwrite($file, 'case '.$i.': break;'. "\n"); 
} 
fwrite($file, 
'} 
echo \'switch took: \', microtime(true) - $start, "\n";' . "\n"); 

dane wynikowe (dla numof = 100000):

i: 0 
elseif took: 6.2942504882812E-5 
switch took: 3.504753112793E-5 

i: 10 
elseif took: 6.4849853515625E-5 
switch took: 4.3869018554688E-5 

i: 100 
elseif took: 0.00014805793762207 
switch took: 0.00011801719665527 

i: 1000 
elseif took: 0.00069785118103027 
switch took: 0.00098896026611328 

i: 10000 
elseif took: 0.0059938430786133 
switch took: 0.0074150562286377 

i: 100000 (first non-existing offset) 
elseif took: 0.043318033218384 
switch took: 0.075783014297485 

został uruchomiony skrypt na moim komputerze stare i powolne okien z PHP 5.3.1 lub 5.3.2, dunno dobrze wiem.

+10

+1 za zrobienie czegoś, aby faktycznie spróbować zmierzyć różnicę wydajności, aby dać poprawną odpowiedź na pytanie, które zadajesz. – Kmeixner