Quale metodo è preferito strstr o strpos?


84

Ho notato che molti sviluppatori utilizzano sia strstr che strpos per verificare l'esistenza di una sottostringa. Uno di loro è preferito e perché?


2
il benchmark che hai menzionato è versus substr not strstr
Flask

Risposte:


126

Dal manuale in linea di PHP :

Se vuoi solo determinare se un particolare ago si trova all'interno del pagliaio, usa invece la funzione più veloce e con meno memoria strpos() .


13
+1, puoi usare strpos o stripos. e non dimenticare di controllare gli avvertimenti sul documento php sull'uso di === FALSE;
fedmich

7
Per approfondire il commento di fedmich: io uso sempre if(strpos($haystack,$needle) !== false) { // do something }, mai if(strpos($haystack,$needle)) { // do bad things }. strposrestituirà 0 se $needleè all'inizio di $haystacke 0 è considerato uguale a falso. (0 == false)restituisce true. (0 === false)restituisce false.
Buttle Butkus

1
Le persone che provengono da C potrebbero pensare di usare la funzione strchr , ma in PHP è in realtà un alias per strstr , quindi strpos è una scelta migliore.
e2-e4

38

Ecco alcune altre risposte (+ benchmark) che ho ottenuto alla mia domanda, che è quasi la stessa (non avevo realizzato la tua quando me lo chiedevo).


Nel frattempo ho anche fatto il mio test di benchmark, che mi sono imbattuto 1000000 volte per ogni funzioni rilevanti ( strstr(), strpos(), stristr()e stripos()).
Ecco il codice:

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

?>

Ed ecco il primo output, che mostra che strpos()è il vincitore :

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 

Il prossimo è simile al primo output ( strpos()è di nuovo il vincitore):

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

Di seguito è un altro, che è più interessante, perché in questo caso, strstr()è il vincitore:

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

Ciò significa che può davvero dipendere da "circostanze ambientali" , che a volte sono difficili da influenzare, e può cambiare il risultato di "attività di microottimizzazione" come questa, nel caso in cui tu stia solo controllando se una stringa esiste o meno in un'altra.

MA penso che nella maggior parte dei casi, strpos()è il vincitore rispetto a strstr().

Spero che questo test sia stato utile per qualcuno.


3
Sebbene questo benchmark sia utile, non misura il consumo di memoria, inoltre non tiene conto delle stringhe lunghe, come kbyte o mbyte.

Eh? @ user133408 Stringhe lunghe e stringhe di byte più grandi richiederebbero anche più tempo.
NiCk Newman

7

Molti sviluppatori usano strposper scopi di micro ottimizzazione .

L'uso funziona strstranche solo se la stringa risultante non può essere interpretata come falsa nel contesto booleano.


11
Non è micro ottimizzazione, si chiama usare la funzione giusta per il lavoro . Se voglio la posizione della stringa, chiamo strpos(). Se volevo la sottostringa dopo quella posizione, chiamo strstr().
Alnitak

1
@ Alnitak: quello che stavo dicendo. Se vuoi verificare la presenza di una stringa, allora c'è una funzione per quello. Se davvero hai bisogno della posizione, ce n'è un'altra. - Quando si sonda la posizione senza effettivamente averne bisogno, difficilmente "si utilizza la funzione giusta per il lavoro". L'intenzione è chiaramente quella di ottimizzare i micro secondi di distanza. (Non è quello che hai citato?)
mario

1
@mario ma non esiste alcuna funzione il cui unico scopo sia controllare se esiste una sottostringa. La posizione della sottostringa (se trovata) è un'informazione libera una volta che l'hai effettivamente trovata. OTOH strstrfa più di quanto è richiesto, motivo per cui è più lento.
Alnitak

@ Alnitak: attenzione, non notizie. Sembri molto irremovibile nel sottolineare la differenza di prestazioni, e solo quella. Questo è un segno rivelatore di micro ottimizzazione. Non fa un blip nel profiler . Dove fa la differenza è nella leggibilità del codice.
mario

@mario in realtà a me interesserebbe solo leggermente la performance. Mi interessa molto usare la funzione giusta per il lavoro ;-)
Alnitak

0

strpos () rileva dove giace un particolare ago nel pagliaio. stristr () verifica se l'ago si trova in un punto qualsiasi del pagliaio

quindi strpos () è più veloce e consuma meno memoria

un motivo per strstr (): se il tuo ago è all'inizio di una stringa, strpos restituisce 0 (quindi devi controllarlo con === false)


6
questa è una spiegazione completamente falsa: strstr()restituisce tutto prima o dopo l'ago, quindi deve prima fare l'equivalente di strpos() e poi creare quella sottostringa . Ecco dove si trova il successo in termini di prestazioni.
Alnitak

-2

Preferisco strstr()per leggibilità e facile codifica .. strpos() !==false è un po 'confuso ..


1
strstrè troppo simile astrtr
Mārtiņš Briedis il

strstrnecessita anche di un confronto rigoroso Esempio:('123450', '0')
Elvis Ciotti
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.