Welche Methode wird strstr oder strpos bevorzugt?

83

Ich habe festgestellt, dass viele Entwickler sowohl strstr als auch strpos verwenden, um nach einer Teilstring-Existenz zu suchen. Wird einer von ihnen bevorzugt und warum?

Nascar
quelle
2
Der Benchmark, den Sie erwähnt haben, ist versus substr not strstr
Flask

Antworten:

124

Aus dem PHP- Online-Handbuch :

Wenn Sie nur feststellen möchten, ob eine bestimmte Nadel im Heuhaufen vorkommt, verwenden Sie strpos() stattdessen die schnellere und weniger speicherintensive Funktion .

Alnitak
quelle
13
+1, Sie können Strpos oder Stripos verwenden. und vergessen Sie nicht, die Warnungen im PHP-Dokument über die Verwendung von === FALSE zu überprüfen;
Fedmich
7
Um auf Fedmichs Kommentar einzugehen: Ich benutze immer if(strpos($haystack,$needle) !== false) { // do something }, niemals if(strpos($haystack,$needle)) { // do bad things }. strposgibt 0 zurück, wenn das $needleganz am Anfang von steht $haystack, und 0 wird als gleich false angesehen. (0 == false)bewertet als wahr. (0 === false)ergibt false.
Buttle Butkus
1
Leute, die aus C kommen, denken vielleicht darüber nach, die strchr- Funktion zu verwenden, aber in PHP ist es tatsächlich ein Alias ​​für strstr , daher ist strpos die bessere Wahl.
e2-e4
37

Hier sind einige andere Antworten (+ Benchmarks), die ich auf meine Frage erhalten habe, die fast dieselbe ist (Ihre habe ich beim Fragen nicht erkannt).


In der Zwischenzeit meine eigenen Benchmark - Test habe ich, was ich lief 1000000 mal auch für jede relevante Funktionen ( strstr(), strpos(), stristr()und stripos()).
Hier ist der Code:

<?php

function getmicrotime() {
    list($usec, $sec) = explode(" ", microtime());
    return ((float) $usec + (float) $sec);
}

$mystring = 'blahblahblah';  
$findme = 'bla';  

echo 'strstr & strpos TEST:<pre>';
$time_start = getmicrotime();
for($i=0; $i<1000000; $i++) strstr($mystring, $findme);
$time_needed_strstr = getmicrotime() - $time_start;
echo 'strstr():            ',
    round( $time_needed_strstr , 8 ). PHP_EOL;

$time_start = getmicrotime();
for($i=0; $i<1000000; $i++) stristr($mystring, $findme);
$time_needed_stristr = getmicrotime() - $time_start;
echo 'stristr():           ',
    round( $time_needed_stristr , 8 ) . PHP_EOL;

$time_start = getmicrotime();
for($i=0; $i<1000000; $i++) strpos($mystring, $findme) !== false;
$time_needed_strpos = getmicrotime() - $time_start;
echo 'strpos() !== false:  ',
    round( $time_needed_strpos , 8 ) . PHP_EOL;

$time_start = getmicrotime();
for($i=0; $i<1000000; $i++) stripos($mystring, $findme) !== false;
$time_needed_stripos = getmicrotime() - $time_start;
echo 'stripos() !== false: ',
    round( $time_needed_stripos , 8 ) . PHP_EOL;

echo PHP_EOL;

echo 'time_needed_stristr - time_needed_strstr: ',
     round( $time_needed_stristr - $time_needed_strstr , 8) . PHP_EOL;
echo 'time_needed_stripos - time_needed_strpos: ',
     round( $time_needed_stripos - $time_needed_strpos , 8) . PHP_EOL;

echo PHP_EOL;

echo 'time_needed_strstr  - time_needed_strpos:  ',
     round( $time_needed_strstr - $time_needed_strpos , 8) . PHP_EOL;
echo 'time_needed_stristr - time_needed_stripos: ',
     round( $time_needed_stristr - $time_needed_stripos , 8) . PHP_EOL;

echo '</pre>';

?>

Und hier ist die erste Ausgabe, die zeigt, dass dies strpos()der Gewinner ist :

strstr & strpos TEST:
strstr():            2.39144707
stristr():           3.65685797
strpos() !== false:  2.39055395
stripos() !== false: 3.54681897

time_needed_stristr - time_needed_strstr: 1.2654109
time_needed_stripos - time_needed_strpos: 1.15626502

time_needed_strstr  - time_needed_strpos:  0.00089312
time_needed_stristr - time_needed_stripos: 0.110039 

Die nächste ähnelt der ersten Ausgabe ( strpos()ist wieder der Gewinner):

strstr & strpos TEST:
strstr():            2.39969015
stristr():           3.60772395
strpos() !== false:  2.38610101
stripos() !== false: 3.34951186

time_needed_stristr - time_needed_strstr: 1.2080338
time_needed_stripos - time_needed_strpos: 0.96341085

time_needed_strstr  - time_needed_strpos:  0.01358914
time_needed_stristr - time_needed_stripos: 0.25821209

Unten ist eine andere, die interessanter ist, weil in diesem Fall strstr()der Gewinner ist:

strstr & strpos TEST:
strstr():            2.35499191
stristr():           3.60589004
strpos() !== false:  2.37646604
stripos() !== false: 3.51773095

time_needed_stristr - time_needed_strstr: 1.25089812
time_needed_stripos - time_needed_strpos: 1.14126492

time_needed_strstr  - time_needed_strpos:  -0.02147412
time_needed_stristr - time_needed_stripos: 0.08815908

Dies bedeutet, dass es wirklich von "Umgebungsbedingungen" abhängen kann , die manchmal schwer zu beeinflussen sind, und das Ergebnis solcher "Mikrooptimierungsaufgaben" ändern kann, falls Sie nur prüfen, ob eine Zeichenfolge in einer anderen vorhanden ist oder nicht.

ABER ich denke in den meisten Fällen strpos()ist der Gewinner im Vergleich zustrstr() .

Ich hoffe, dieser Test war für jemanden nützlich.

Sk8erPeter
quelle
3
Dieser Benchmark ist zwar nützlich, misst jedoch nicht den Speicherverbrauch und berücksichtigt auch keine langen Zeichenfolgen wie KB oder MB.
Huh? @ user133408 Lange Zeichenfolgen und Zeichenfolgen mit größerem Byte würden sogar länger dauern.
NiCk Newman
7

Viele Entwickler verwenden strposfür Mikrooptimierungszwecke .

Die Verwendung strstrfunktioniert auch nur, wenn die resultierende Zeichenfolge im booleschen Kontext nicht als falsch interpretiert werden kann.

Mario
quelle
11
Es handelt sich nicht um eine Mikrooptimierung, sondern um die Verwendung der richtigen Funktion für den Job . Wenn ich die Position der Zeichenfolge haben möchte, rufe ich an strpos(). Wenn ich den Teilstring nach dieser Position haben wollte, rufe ich an strstr().
Alnitak
1
@ Alnitak: Was ich gesagt habe. Wenn Sie prüfen möchten, ob eine Zeichenfolge vorhanden ist, gibt es dafür eine Funktion. Wenn Sie die Position tatsächlich brauchen, gibt es eine andere. - Wenn Sie nach der Position suchen, ohne die Position tatsächlich zu benötigen, dann ist das kaum "die richtige Funktion für den Job verwenden". Die Absicht ist eindeutig, Mikrosekunden entfernt zu optimieren. (Ist es nicht das, was Sie zitiert haben?)
Mario
1
@mario, aber es gibt keine Funktion, deren einziger Zweck darin besteht, zu überprüfen, ob ein Teilstring vorhanden ist. Die Position des Teilstrings (falls gefunden) ist eine freie Information, sobald Sie sie tatsächlich gefunden haben. OTOH strstrmacht mehr als nötig, weshalb es langsamer ist.
Alnitak
@Alnitak: Wohlgemerkt, keine Neuigkeiten. Sie scheinen sehr darauf bedacht zu sein, auf den Leistungsunterschied hinzuweisen, und nur das. Das ist ein verräterisches Zeichen für Mikrooptimierung. Es macht keinen Fehler im Profiler . Wo es einen Unterschied macht, ist die Lesbarkeit des Codes.
Mario
@mario eigentlich würde mich die leistung nur sehr wenig interessieren. Es ist mir sehr wichtig, die richtige Funktion für den Job zu verwenden ;-)
Alnitak
0

strpos () erkennt, wo im Heuhaufen eine bestimmte Nadel liegt. stristr () prüft, ob sich die Nadel irgendwo im Heuhaufen befindet

Daher ist strpos () schneller und weniger speicherintensiv

ein Grund für strstr (): Wenn sich Ihre Nadel am Anfang eines Strings befindet, gibt strpos 0 zurück (müssen Sie dies also mit === false überprüfen).

Flasche
quelle
6
Das ist eine völlig falsche Erklärung - strstr()gibt alles vor oder nach der Nadel zurück, also muss es zuerst das Äquivalent von machen strpos() und dann diesen Teilstring erstellen . Hier liegt der Performance-Hit.
Alnitak
-2

Ich bevorzuge strstr()für Lesbarkeit und einfache Codierung .. strpos() !==false ist ein bisschen verwirrend ..

T.Todua
quelle
1
strstrist zu ähnlich zustrtr
Mārtiņš Briedis
strstrbraucht auch einen strengen Vergleich Beispiel:('123450', '0')
Elvis Ciotti