¿Qué método es strstr o strpos preferido?

84

Noté que muchos desarrolladores están usando strstr y strpos para verificar la existencia de una subcadena. ¿Es uno de ellos el preferido y por qué?

nascar
fuente
2
el punto de referencia que mencionó es versus substr no strstr
Frasco

Respuestas:

125

Desde el manual en línea de PHP :

Si solo desea determinar si una aguja en particular se encuentra dentro del pajar, use la función más rápida y menos intensiva en memoria strpos() .

Alnitak
fuente
13
+1, puede utilizar strpos o stripos. y no olvide revisar las advertencias en el documento php sobre el uso de === FALSE;
fedmich
7
Para ampliar el comentario de fedmich: siempre uso if(strpos($haystack,$needle) !== false) { // do something }, nunca if(strpos($haystack,$needle)) { // do bad things }. strposdevolverá 0 si $needleestá al principio de $haystack, y 0 se considera igual a falso. (0 == false)se evalúa como verdadero. (0 === false)se evalúa como falso.
Buttle Butkus
1
Las personas que vienen de C pueden pensar en usar la función strchr , pero en PHP es en realidad un alias para strstr , por lo que strpos es una mejor opción.
e2-e4
38

Aquí hay algunas otras respuestas (+ puntos de referencia) que obtuve a mi pregunta, que es casi la misma (no me di cuenta de la tuya al preguntar).


Mientras tanto también hice mi propia prueba de referencia, lo que me encontré 1000000 veces para cada funciones relevantes ( strstr(), strpos(), stristr()y stripos()).
Aquí está el código:

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

?>

Y aquí está el primer resultado, que muestra que strpos()es el ganador :

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 

El siguiente es similar al primer resultado ( strpos()es el ganador nuevamente):

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

A continuación se muestra otro, que es más interesante, porque en este caso, strstr()es el ganador:

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

Esto significa que realmente puede depender de "circunstancias ambientales" , que a veces son difíciles de influir, y pueden cambiar el resultado de "tareas de microoptimización" como esta, en caso de que solo esté comprobando si una cadena existe en otra o no.

PERO creo que en la mayoría de los casos, strpos()es el ganador en comparación constrstr() .

Espero que esta prueba haya sido útil para alguien.

Sk8erPeter
fuente
3
Si bien este punto de referencia es útil, no mide el consumo de memoria, tampoco tiene en cuenta cadenas largas, como kbytes o mbytes.
¿Eh? @ user133408 Las cadenas largas y las cadenas de bytes más grandes llevarían incluso más tiempo.
NiCk Newman
7

Muchos desarrolladores utilizan strpospara la microoptimización fines de .

El uso strstrtambién solo funciona si la cadena resultante no se puede interpretar como falsa en un contexto booleano.

mario
fuente
11
No es una micro optimización, se llama usar la función correcta para el trabajo . Si quiero la posición de la cuerda, llamo strpos(). Si quisiera la subcadena después de esa posición, llamo strstr().
Alnitak
1
@Alnitak: Lo que estaba diciendo. Si desea verificar la presencia de una cadena, entonces hay una función para eso. Si realmente necesita el puesto, entonces hay otro. - Cuando busca la posición sin necesidad de la posición, entonces difícilmente es "usar la función correcta para el trabajo". La intención es claramente optimizar los microsegundos. (¿No es eso lo que citó?)
mario
1
@mario pero no hay ninguna función cuyo único propósito sea comprobar si existe una subcadena. La posición de la subcadena (si se encuentra) es información gratuita una vez que la haya encontrado. OTOH, strstrhace más de lo necesario, por lo que es más lento.
Alnitak
@Alnitak: Eso sí, no noticias. Pareces muy firme en señalar la diferencia de rendimiento, y solo eso. Esa es una señal reveladora de la microoptimización. No hace ningún ruido en el generador de perfiles . Donde sí marca la diferencia es en la legibilidad del código.
mario
@mario en realidad me importaría muy poco la actuación. Me importa mucho usar la función correcta para el trabajo ;-)
Alnitak
0

strpos () detecta en qué parte del pajar se encuentra una aguja en particular. stristr () prueba si la aguja está en algún lugar del pajar

por lo tanto, strpos () es más rápido y consume menos memoria

una razón para strstr (): si su aguja está al comienzo de una cadena, strpos devuelve 0 (así que debe verificarlo con === falso)

Matraz
fuente
6
esa es una explicación completamente falsa: strstr()devuelve todo antes o después de la aguja, por lo que primero tiene que hacer el equivalente de strpos() y luego crear esa subcadena . Ahí es donde está el impacto en el rendimiento.
Alnitak
-2

Prefiero la strstr()legibilidad y la codificación fácil ... strpos() !==false es un poco confuso ...

T.Todua
fuente
1
strstres demasiado similar astrtr
Mārtiņš Briedis
strstrtambién necesita una comparación estricta Ejemplo:('123450', '0')
Elvis Ciotti