Diese Frage ist nur für mich, da ich immer gerne optimierten Code schreibe, der auch auf billigen langsamen Servern (oder Servern mit viel Verkehr) ausgeführt werden kann.
Ich sah mich um und konnte keine Antwort finden. Ich habe mich gefragt, was zwischen diesen beiden Beispielen schneller ist, wenn ich bedenke, dass die Schlüssel des Arrays in meinem Fall nicht wichtig sind (Pseudocode natürlich):
<?php
$a = array();
while($new_val = 'get over 100k email addresses already lowercased'){
if(!in_array($new_val, $a){
$a[] = $new_val;
//do other stuff
}
}
?>
<?php
$a = array();
while($new_val = 'get over 100k email addresses already lowercased'){
if(!isset($a[$new_val]){
$a[$new_val] = true;
//do other stuff
}
}
?>
Da der Punkt der Frage nicht die Array-Kollision ist, möchte ich hinzufügen, dass $a[$new_value]
Sie verwenden können , wenn Sie Angst vor kollidierenden Inserts haben $a[md5($new_value)]
. Es kann immer noch Kollisionen verursachen, würde jedoch einen möglichen DoS-Angriff verhindern, wenn aus einer vom Benutzer bereitgestellten Datei gelesen wird ( http://nikic.github.com/2011/12/28/Supercolliding-a-PHP-array.html ).
quelle
Antworten:
Die bisherigen Antworten sind genau richtig. Die Verwendung ist
isset
in diesem Fall schneller, weilin_array
jeder Wert überprüft werden muss, bis eine Übereinstimmung gefunden wird.in_array
integrierten Funktion.Diese können mithilfe eines Arrays mit Werten (10.000 im folgenden Test) demonstriert werden, wodurch
in_array
mehr Suchen erforderlich wird.Dies baut auf Jasons Benchmark auf, indem einige zufällige Werte eingegeben und gelegentlich ein Wert gefunden wird, der im Array vorhanden ist. Alles zufällig, also Vorsicht, dass die Zeiten schwanken.
quelle
isset()
ist schneller.Während es offensichtlich sein sollte,
isset()
testet nur ein einzelner Wert. Währendin_array()
wird über das gesamte Array iteriert und der Wert jedes Elements getestet.Grobes Benchmarking ist recht einfach
microtime()
.Ergebnisse:
Hinweis: Die Ergebnisse waren ähnlich, unabhängig davon, ob sie vorhanden waren oder nicht.
Code:
Zusätzliche Ressourcen
Ich möchte Sie ermutigen, sich auch Folgendes anzuschauen:
quelle
microtime()
anderen Tools teilen . Unglaublich wertvoll.in_array
Funktion im Vergleich zur Verwendung desisset
integrierten Schlüssels hervorgehoben . Dies ist besser mit einem Array, das eine Reihe zufälliger Schlüssel enthält und gelegentlich nach einem vorhandenen Schlüssel / Wert sucht.while
undforeach
bei jeder Aktualisierung unterschiedliche "Gewinner" bekam. Es hängt immer von zu vielen Servervariablen ab. Das Beste ist, eine sehr große Anzahl von Malen zu unterschiedlichen Zeiten zu durchlaufen und diejenige zu erhalten, die häufiger gewinnt, oder einfach zu wissen, was im Hintergrund passiert, und zu wissen, dass es der endgültige Gewinner sein wird egal wasisset()
ist, warum denken Sie dann , wenn Sie ihn an ein größeres Array übergeben, wird er schneller ?Die Verwendung
isset()
nutzt die schnellere Suche, da eine Hash-Tabelle verwendet wird , sodass keineO(n)
Suche erforderlich ist .Der Schlüssel wird zuerst mit der djb-Hash-Funktion gehasht, um den Bucket mit ähnlich gehashten Schlüsseln zu bestimmen
O(1)
. Der Bucket wird dann iterativ durchsucht, bis der genaue Schlüssel in gefunden istO(n)
.Abgesehen von absichtlichen Hash-Kollisionen bietet dieser Ansatz eine viel bessere Leistung als
in_array()
.Beachten Sie, dass bei der Verwendung
isset()
in der von Ihnen gezeigten Weise zum Übergeben der endgültigen Werte an eine andere Funktion diearray_keys()
Erstellung eines neuen Arrays erforderlich ist . Ein Speicherkompromiss kann erzielt werden, indem die Daten sowohl in den Schlüsseln als auch in den Werten gespeichert werden.Aktualisieren
Um zu sehen, wie sich Ihre Entscheidungen zum Code-Design auf die Laufzeitleistung auswirken, können Sie die kompilierte Version Ihres Skripts überprüfen :
echo isset($arr[123])
echo in_array(123, $arr)
Es wird nicht nur
in_array()
eine relativ ineffizienteO(n)
Suche verwendet, sondern es muss auch eine Funktion (DO_FCALL
) aufgerufen werden, während hierfürisset()
ein einzelner Opcode (ZEND_ISSET_ISEMPTY_DIM_OBJ
) verwendet wird.quelle
Der zweite ist schneller, da nur nach diesem bestimmten Array-Schlüssel gesucht wird und nicht über das gesamte Array iteriert werden muss, bis es gefunden wird (jedes Array-Element wird angezeigt, wenn es nicht gefunden wird).
quelle
isset()
du nicht das ganze Array betrachten, auch wenn es nicht gefunden wird?