Która metoda jest preferowana strstr czy strpos?

84

Zauważyłem, że wielu programistów używa zarówno strstr, jak i strpos do sprawdzania istnienia podciągów. Czy jeden z nich jest preferowany i dlaczego?

nascar
źródło
2
benchmark, o którym wspomniałeś, to porównanie z substr, a nie strstr
Flask

Odpowiedzi:

125

Z podręcznika online PHP :

Jeśli chcesz tylko ustalić, czy dana igła występuje w stogu siana, strpos() zamiast tego użyj szybszej i mniej wymagającej pamięci funkcji .

Alnitak
źródło
13
+1, możesz użyć striptizu lub striptizu. i nie zapomnij sprawdzić ostrzeżeń w dokumencie php o używaniu === FALSE;
fedmich
7
Aby rozwinąć komentarz fedmicha: zawsze używam if(strpos($haystack,$needle) !== false) { // do something }, nigdy if(strpos($haystack,$needle)) { // do bad things }. strposzwróci 0, jeśli $needleznajduje się na samym początku $haystack, a 0 zostanie uznane za równe fałszowi. (0 == false)zwraca wartość true. (0 === false)ocenia jako fałsz.
Buttle Butkus
1
Ludzie pochodzący z C mogą pomyśleć o użyciu funkcji strchr , ale w PHP jest to właściwie alias dla strstr , więc strpos jest lepszym wyborem.
e2-e4
38

Oto kilka innych odpowiedzi (+ benchmarki), które otrzymałem na moje pytanie, które jest prawie takie samo (nie zdawałem sobie sprawy z twojego pytania).


W międzyczasie również własną testu porównawczego, który wpadłem 1000000 razy dla każdej odpowiedniej funkcji ( strstr(), strpos(), stristr()i stripos()).
Oto kod:

<?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>';

?>

A oto pierwsze wyjście, które pokazuje, że strpos()jest zwycięzcą :

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 

Następny jest podobny do pierwszego wyjścia ( strpos()znowu jest zwycięzcą):

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

Poniżej kolejny, ciekawszy, bo w tym przypadku strstr()wygrywa:

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

Oznacza to, że może to naprawdę zależeć od „okoliczności środowiskowych” , na które czasami trudno wpływać, i może zmienić wynik takich „zadań mikrooptymalizacji”, w przypadku gdy po prostu sprawdzasz, czy ciąg istnieje w innym, czy nie.

ALE myślę, że w większości przypadków strpos()jest zwycięzcą w porównaniu do strstr().

Mam nadzieję, że ten test był dla kogoś przydatny.

Sk8erPeter
źródło
3
Chociaż ten test porównawczy jest przydatny, nie mierzy zużycia pamięci, ale także nie bierze pod uwagę długich ciągów, takich jak kilobajty lub megabajty.
Co? @ user133408 Długie i większe ciągi bajtów zajęłyby nawet więcej czasu.
NiCk Newman,
7

Wielu programistów używa strposdo mikrooptymalizacji .

Używanie strstrrównież działa tylko wtedy, gdy wynikowy ciąg nie może być interpretowany jako fałsz w kontekście logicznym.

mario
źródło
11
To nie jest mikro optymalizacja, nazywa się to użyciem odpowiedniej funkcji do zadania . Jeśli chcę pozycję struny, wołam strpos(). Gdybym chciał mieć podciąg po tej pozycji, dzwonię strstr().
Alnitak
1
@Alnitak: Co mówiłem. Jeśli chcesz sprawdzić obecność łańcucha, jest do tego funkcja. Jeśli rzeczywiście potrzebujesz tej pozycji, jest inna. - Kiedy próbujesz znaleźć pozycję bez faktycznej potrzeby jej określenia, nie jest to „używanie odpowiedniej funkcji do pracy”. Intencją jest oczywiście zoptymalizowanie mikrosekund. (Czy to nie jest to, co cytowałeś?)
mario
1
@mario, ale nie ma funkcji, której jedynym celem jest sprawdzenie, czy istnieje podciąg. Pozycja z fragmentu (jeśli znalezione) jest bezpłatne informacje kiedy już rzeczywiście znalazł. OTOH strstrrobi więcej niż jest to wymagane, dlatego działa wolniej.
Alnitak
@Alnitak: Pamiętaj, nie wiadomości. Wydajesz się bardzo nieugięty, jeśli chodzi o wskazywanie różnicy w wydajności i tylko to. To znak rozpoznawczy mikro optymalizacji. Nie robi żadnego śladu w profilerze . To, co robi różnicę, polega na czytelności kodu.
mario
@mario właściwie tylko nieznacznie przejmowałbym się wydajnością. Bardzo zależy mi na używaniu odpowiedniej funkcji do pracy ;-)
Alnitak
0

strpos () wykrywa, gdzie w stogu siana leży dana igła. stristr () sprawdza, czy igła znajduje się gdziekolwiek w stogu siana

dlatego strpos () jest szybsza i mniej zużywa pamięć

powód dla strstr (): jeśli twoja igła znajduje się na początku łańcucha, strpos zwraca 0 (więc musisz to sprawdzić za pomocą === false)

Kolba
źródło
6
to jest całkowicie fałszywe wyjaśnienie - strstr()zwraca wszystko przed lub po igle, więc najpierw musi wykonać odpowiednik, strpos() a następnie utworzyć ten podciąg . Tam jest hit wydajnościowy.
Alnitak
-2

Wolę strstr()czytelność i łatwe kodowanie .. strpos() !==false jest trochę zagmatwane ..

T.Todua
źródło
1
strstrjest zbyt podobny dostrtr
Mārtiņš Briedis.
strstrrównież potrzebuje ścisłego porównania Przykład:('123450', '0')
Elvis Ciotti