2008-11-27 8 views
15

Ist es schneller folgendes zu tun:Was ist schneller: in_array() oder eine Menge Ausdrücke in PHP?

if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') { ... } 

Oder:

if (!in_array($var, array('test1', 'test2', 'test3', 'test4') { ... } 

Gibt es eine Anzahl von Werten, an welcher Stelle es schneller ist das eine oder andere zu tun?

(In diesem Fall wird die Anordnung in der zweiten Option existiert nicht alreay.)

+0

Off Thema leicht - haben Sie nur Ihre andere Frage von vor ein paar Minuten gelöscht, oder werde ich verrückt? – Greg

Antwort

14

Ich schlage vor, nur stark würde in_array() verwenden, würde jede Geschwindigkeitsdifferenz vernachlässigbar sein, aber die Lesbarkeit der einzelnen Variablen testen getrennt ist schrecklich.

nur zum Spaß hier ist ein Test ich lief:

$array = array('test1', 'test2', 'test3', 'test4'); 
$var = 'test'; 
$iterations = 1000000; 

$start = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') {} 
} 
$end = microtime(true); 

print "Time1: ". ($end - $start)."<br />"; 

$start2 = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    if (!in_array($var, $array)) {} 
} 
$end2 = microtime(true); 

print "Time2: ".($end2 - $start2)."<br />"; 

// Time1: 1.12536692619 
// Time2: 1.57462596893 

leicht triviale Anmerkung zu beachten gilt, wenn $var nicht gesetzt ist, Verfahren 1 dauert viel länger (je nachdem, wie viele Bedingungen Sie Test)

+0

Mit welcher PHP-Version arbeiten Sie? 5.2.6 (Windows) gibt Time1: 1.36 Time2: 4.88 - das ist ein großer Unterschied – Greg

+1

Auch Sie betrügen leicht, indem Sie das Array (...) aus der Schleife nehmen - wenn Sie es verwenden, wie die Frage sagt, meine time2 geht zu über 6 Sekunden – Greg

+0

5.2.5 (mac os x), ich bekomme ~ 1.25: ~ 4 mit der nicht-betrügerischen Version – Owen

5

Die erste wird schneller sein - die zweite hat viel Aufwand: Erstellen des Arrays, Aufruf einer Funktion, Durchsuchen des Arrays ...

Allerdings, wie ich in einer Frage ein paar Antworten nach unten gesagt, ist vorzeitige Optimierung die Wurzel allen Übels. Sie sollten Ihren Code schreiben, um lesbar zu sein, dann wenn es optimiert werden muss, dann optimieren Sie es.

Edit:

Meine Timings mit @ Owen Code (PHP 5.2.6/Windows):

Time1: 1.33601498604 
Time2: 4.9349629879 

Verschieben des Array (...) innerhalb der Schleife, wie in der Frage:

Time1: 1.34736609459 
Time2: 6.29464697838 
+0

bizarr :(sollte irgendwie weg sein, dass – Owen

+0

Hoppla, Entschuldigung für das Vertippen Ihres Namens Owen! – Greg

2

in_array wird für eine große Anzahl von Elementen schneller sein. "groß" ist sehr subjektiv, basierend auf vielen Faktoren, die mit den Daten und Ihrem Computer zusammenhängen. Da Sie fragen, nehme ich an, Sie haben es nicht mit einer unbedeutenden Anzahl von Gegenständen zu tun. Für längere Listen notieren Sie this information und messen Sie die Leistung mit einem umgedrehten Array, so dass PHP Hash-Lookups anstelle einer linearen Suche verwenden kann. Bei einem "statischen" Array kann diese Optimierung die Leistung möglicherweise nicht verbessern, kann es aber auch sein.

Owens Testcode verwenden, mit einem blätterte Array und mehr Iterationen für konsistentere Ergebnisse:

$array2 = array_flip($array); 
$iterations = 10000000; 

$start = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    if (!isset($array2[$var])) {} 
} 
$end = microtime(true); 
print "Time3: ".($end - $start)."<br />"; 

Time1: 12.875 
Time2: 13.7037701607 
Time3: 3.70514011383 
+0

Kleiner Kommentar: Umdrehen einer großen Reihe Ich verwende viel Speicher. –

+1

Das Array kann in der gekippten Konfiguration deklariert werden. – Sparr

6

Beachten Sie, wenn Sie eine Reihe von !== Aussagen zu ersetzen suchen, sollten Sie den dritten Parameter übergeben zu in_array als true, die Typprüfung für die Elemente im Array erzwingt.

Gewöhnliche != erfordert dies offensichtlich nicht.

1

Beachten Sie, dass, wie RoBorg darauf hingewiesen hat, beim Erstellen des Arrays Overhead auftritt, sodass es innerhalb der Iterationsschleife verschoben werden sollte. Aus diesem Grund ist Sparrs Beitrag auch ein wenig irreführend, da es Overhead mit der array_flip-Funktion gibt.

Hier ist ein weiteres Beispiel mit allen 5 Variationen:

$array = array('test1', 'test2', 'test3', 'test4'); 
$var = 'test'; 
$iterations = 1000000; 

$start = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') {} 
} 
print "Time1: ". (microtime(true) - $start); 

$start = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    if (!in_array($var, $array)) {} 
} 
print "Time2: ".(microtime(true) - $start); 

$start = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    if (!in_array($var, array('test1', 'test2', 'test3', 'test4'))) {} 
} 
print "Time2a: ".(microtime(true) - $start); 

$array2 = array_flip($array); 
$start = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    if (!isset($array2[$var])) {} 
} 
print "Time3: ".(microtime(true) - $start); 

$start = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    $array2 = array_flip($array); 
    if (!isset($array2[$var])) {} 
} 
print "Time3a: ".(microtime(true) - $start); 

Meine Ergebnisse:

Time1 : 0.59490108493 // straight comparison 
Time2 : 0.83790588378 // array() outside loop - not accurate 
Time2a: 2.16737604141 // array() inside loop 
Time3 : 0.16908097267 // array_flip outside loop - not accurate 
Time3a: 1.57209014893 // array_flip inside loop 

Zusammengefasst mit array_flip (mit isset) ist schneller als InArray aber nicht so schnell wie ein gerade Vergleich .

+0

Das Array nicht in der Schleife spiegeln. Ändere es in $ array2 = array ('test1' => 0, 'test2' => 0, 'test3' => 0, 'test4' => 0); und versuche es erneut. Im ersten Fall ist das Array so konstruiert, dass Sie in diesem Fall auch das Array konstruieren sollten. – jmucchiello

+0

über den obigen Kommentar, Isset wird false auf 0 als val zurückgeben, besser, 1 als val zu verwenden oder array_key_exists zu verwenden – Jason

1

Hallo Ich habe gerade diesen Fall auf der Spitze und wies darauf hin, dass mit zunehmender Anzahl von Werten Ebene Vergleich ist nicht die performante Art und Weise.

$var = 'test'; 
$num_values = 1000; 
$iterations = 1000000; 
print "\nComparison performance test with ".$num_values." values and ".$iterations." loop iterations"; 
print "\n"; 

$start = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    if ($var != 'test0' && 
     $var != 'test1' && 
     // ... 
     // yes I really have 1000 lines in my file 
     // ... 
     $var != 'test999') {} 
} 
print "\nCase 1: plain comparison"; 
print "\nTime 1: ". (microtime(true) - $start); 
print "\n"; 

$start = microtime(true); 
$array = array(); 
for($i=0; $i<$num_values; $i++) { 
    $array1[] = 'test'.$i; 
} 
for($i = 0; $i < $iterations; ++$i) { 
    if (!in_array($var, $array1)) {} 
} 
print "\nCase 2: in_array comparison"; 
print "\nTime 2: ".(microtime(true) - $start); 
print "\n"; 

$start = microtime(true); 
$array = array(); 
for($i=0; $i<$num_values; $i++) { 
    $array2['test'.$i] = 1; 
} 
for($i = 0; $i < $iterations; ++$i) { 
    if (!isset($array2[$var])) {} 
} 
print "\nCase 3: values as keys, isset comparison"; 
print "\nTime 3: ".(microtime(true) - $start); 
print "\n"; 

$start = microtime(true); 
$array = array(); 
for($i=0; $i<$num_values; $i++) { 
    $array3['test'.$i] = 1; 
} 
for($i = 0; $i < $iterations; ++$i) { 
    if (!array_key_exists($var, $array3)) {} 
} 
print "\nCase 4: values as keys, array_key_exists comparison"; 
print "\nTime 4: ".(microtime(true) - $start); 
print "\n"; 

Meine Ergebnisse (PHP 5.5.9):

Case 1: plain comparison 
Time 1: 31.616894006729 

Case 2: in_array comparison 
Time 2: 23.226133823395 

Case 3: values as keys, isset comparison 
Time 3: 0.050863981246948 

Case 4: values as keys, array_key_exists comparison 
Time 4: 0.13700890541077 

Ich bin damit einverstanden, das ist ein wenig extrem, aber es zeigt das große Bild und das große Potenzial in

Hier ist mein Code die Hash-Tabelle-ähnlichen assoziativen Arrays von PHP, müssen Sie nur verwenden

1

Wenn Sie von PHP sprechen und fragen, ob:

  • eine Reihe von "if" s und "else ifs",
  • ein "if" mit einer Reihe von "oder" ed Bedingungen (wie in den ursprünglichen Beitrag Details) oder
  • Verwendung von „in_array "mit einem on-the-fly aufgebaut Array,

ist besser,

sollte man bedenken, dass die PHP-Sprache‚switch‘Anweisung ist eine Alternative für solche Situationen konzipiert und kann eine bessere Antwort sein . (Obwohl das Beispiel des Posters uns dazu bringt, nur zwei Lösungen zu vergleichen, fragt die eigentliche Fragestellung nach in_array versus PHP Statements, also denke ich, dass das faires Spiel ist).

In dem Beispiel des Plakats, dann würde ich stattdessen empfehlen:

switch ($var) 
{ case 'test1': case 'test2': case 'test3': case 'test4': 
    echo "We have a good value"; break; 
    default: 
    echo "We do not have a good value"; 
} 

ich PHP für ein paar nicht-primitive Konstrukte in den Fällen, wie zum Beispiel eines Komma für „oder“ erlaubt werden soll. Aber das oben Gesagte ist, was die Entwickler von PHP als den klarsten Weg angesehen haben, damit umzugehen. Und es scheint zur Ausführungszeit effizienter zu sein als die anderen beiden Alternativen.

Solange ich über eine Wunschliste rede, wäre das "IN" in SQL noch deutlicher für die Beispielsituation des Posters.

Dieses Denken ist wahrscheinlich das, was den Menschen führt zu wollen „in_array“ zu verwenden, für solche Situationen, aber es ist ein bisschen unglücklich zu haben, eine Datenstruktur zu bauen und dann ein Prädikat verwendet für diese Datenstruktur entworfen, anstatt eine Art, es einfach zu sagen, ohne dass das Overhead passiert.

0

Ich weiß, diese Frage ist fast 10 Jahre alt, aber es gibt andere Möglichkeiten, dies zu tun. Ich habe Methode B von Nick's page mit Tausenden von Einträgen verwendet. Es war unglaublich schnell.

foreach(array_values($haystack) as $v) 
    $new_haystack[$v] = 1; 
} 

// So haystack becomes: 
$arr[“String1”] = 1; 
$arr[“String2”] = 1; 
$arr[“String3”] = 1; 


// Then check for the key: 
if (isset($haystack[$needle])) { 
    echo("needle ".$needle." found in haystack"); 
}