Frage

Ist es schneller Folgendes zu tun:

 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 nicht alreay vorhanden sein.)

War es hilfreich?

Lösung

ich dringend, würde vorschlagen, nur in_array() verwenden, würde jede Geschwindigkeitsdifferenz vernachlässigbar sein, aber die Lesbarkeit jede Variable einzeln testen, schrecklich.

nur zum Spaß hier ist ein Test lief ich:

$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

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

Andere Tipps

Beachten Sie, wenn Sie suchen eine Reihe von !== Aussagen zu ersetzen, sollten Sie den dritten Parameter auf in_array als true, die sich auf die Elemente im Array Überprüfung erzwingt ein.

Ordinary != ist dies nicht erforderlich ist, offensichtlich.

Die erste wird schneller sein - das zweite hat eine Menge Aufwand: das Array zu schaffen, eine Funktion aufrufen, die Suche im Array ...

Aber, wie ich in einer Frage, sagte ein paar Antworten nach unten, ist ein vorzeitige Optimierung ist die Wurzel aller Übel. Sie sollten Ihren Code schreiben, lesbar zu sein, dann , wenn muss es optimiert es profilieren, dann optimieren.

Edit:

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

Time1: 1.33601498604
Time2: 4.9349629879

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

Time1: 1.34736609459
Time2: 6.29464697838

in_array wird schneller für große Stückzahlen. „Groß“ ist sehr subjektiv, basierend auf einer Vielzahl von Faktoren auf die Daten und Ihren Computer verbunden. Da Sie fragen, gehe ich davon aus Sie nicht mit einer trivialen Anzahl der Elemente handelt. Bei längeren Listen, beherzigen diese Informationen , und misst die Leistung mit einem Array umgedreht, so dass PHP-Hash-Lookups verwenden, anstatt eine lineare Suche. Für einen „statischen“ Array, das kann nicht die Leistung zu verbessern zwicken, aber es kann auch.

Mit Owens Testcode 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

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

Hier ist mein Code:

$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 der Hash-Tabelle ähnliche assoziative Arrays von PHP, Sie müssen es nur nutzen

Beachten Sie, dass als RoBorg darauf hingewiesen, es bei der Schaffung des Array-Overhead ist, so dass es innerhalb der Iterationsschleife bewegt werden soll. Aus diesem Grunde ist Sparr die Post auch ein wenig irreführend, da es Overhead mit der array_flip Funktion.

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

Insgesamt array_flip Verwendung (mit isset) schneller als InArray aber nicht so schnell wie ein direkter Vergleich.

Wenn der PHP sprechen und zu 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 Plakats führt uns nur zwei Lösungen zu vergleichen, die eigentliche Frage Überschrift fragt im Vergleich zu PHP-Anweisungen prüfen in_array, so dass ich denke, das faire 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 wünsche PHP für ein paar nicht-primitive Konstrukte in den Fällen erlaubt, wie ein Komma für „oder“. Aber der oben ist, was die Designer von PHP als die klarste Weg, der Umgang mit dieser sein. Und es scheint, als die beiden anderen Alternativen effizienter zur Ausführungszeit zu sein, wie gut.

Solange ich über eine Wunschliste rede, die „IN“ in SQL gefunden wäre noch deutlicher für das Beispielsituation des Plakats.

Dieses Denken ist wahrscheinlich das, was den Menschen führt zu wollen „in_array“ zu verwenden, für solche Situationen, aber es ist eine Art von unglücklichen eine Datenstruktur zu haben, zu bauen und dann ein Prädikat für diese Datenstruktur entworfen verwenden, anstatt ein mit Möglichkeit, nur es zu sagen, ohne dass Aufwand geschieht.

Hier ist ein Live-Update dieser Bank mit einem anderen Fall https://3v4l.org/OA2S7

Die Ergebnisse für PHP 7.3:

  • multiple Vergleiche: 0,0575 07991790771

  • in_array: 0,0256 8507194519

  • array_flip () außerhalb Schleife gemessen + isset (): 0,0146 78001403809

  • array_flip () äußere Schleife nicht gemessen + isset (): 0,0156 50033950806

  • foreach und Vergleich: 0,0627 82049179077

Ich weiß, diese Frage fast 10 Jahre alt ist, aber es gibt auch andere Möglichkeiten, dies zu tun. Ich verwendete Methode B von Nicks Seite mit Tausenden von Einträgen. 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");
}

Mein Testing

$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 />";

$array_flip = array_flip($array);

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

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    if (!isset($array[$var])) {}
}
$end = microtime(true);

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

Zeit1: 0,20001101493835

     

Time2: 0,32601881027222

     

Time3: 0,072004079818726

     

time4: 0,070003986358643

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top