Какой метод предпочтительнее strstr или strpos?

84

Я заметил, что многие разработчики используют как strstr, так и strpos для проверки существования подстроки. Какой из них предпочтительнее и почему?

Джонлемон
источник
2
эталонный тест, который вы упомянули, сравнивается с substr, а не strstr
Flask

Ответы:

126

Из онлайн-руководства PHP :

Если вы хотите только определить, встречается ли конкретная иголка в стоге сена, используйте strpos() вместо этого более быструю и менее интенсивную функцию памяти .

Альнитак
источник
13
+1, вы можете использовать strpos или stripos. и не забудьте проверить предупреждения в документации php об использовании === FALSE;
fedmich
7
Чтобы уточнить комментарий Fedmich: я всегда использую if(strpos($haystack,$needle) !== false) { // do something }, никогда if(strpos($haystack,$needle)) { // do bad things }. strposвернет 0, если $needleнаходится в самом начале $haystack, и 0 считается равным false. (0 == false)оценивается как истина. (0 === false)оценивается как ложь.
Buttle Butkus
1
Люди, пришедшие из C, могут подумать об использовании функции strchr , но в PHP это фактически псевдоним для strstr , поэтому strpos - лучший выбор.
e2-e4
38

Вот еще несколько ответов (+ тесты). Я получил почти такой же вопрос (я не понял вашего, когда спрашивал).


В то же время я также сделал свой собственный тест бенчмарк, который я выбежала 1000000 раз для каждого соответствующих функций ( strstr(), strpos(), stristr()и stripos()).
Вот код:

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

?>

И вот первый результат, который показывает, что strpos()победитель :

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 

Следующий результат аналогичен первому ( strpos()снова победитель):

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

Ниже еще один, более интересный, потому что в этом случае strstr()победитель:

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

Это означает, что это действительно может зависеть от «условий окружающей среды» , на которые иногда трудно повлиять, и может изменить результат подобных «задач микрооптимизации», если вы просто проверяете, существует ли строка в другой строке или нет.

НО я думаю, что в большинстве случаев strpos()это победитель по сравнению с strstr().

Надеюсь, этот тест был кому-то полезен.

Sk8erPeter
источник
3
Хотя этот тест полезен, он не измеряет потребление памяти, а также не принимает во внимание длинные строки, такие как килобайты или мегабайты.
А? @ user133408 Длинные строки и большие байтовые строки могут занять больше времени.
NiCk Newman
7

Многие разработчики используют его strposдля микрооптимизации .

Использование strstrтакже работает только в том случае, если результирующая строка не может быть интерпретирована как ложь в логическом контексте.

Марио
источник
11
Это не микрооптимизация, она вызывается с использованием правильной функции для работы . Если мне нужна позиция строки, я звоню strpos(). Если мне нужна подстрока после этой позиции, я вызываю strstr().
Alnitak
1
@Alnitak: То, что я говорил. Если вы хотите проверить наличие строки, для этого есть функция. Если вам действительно нужна должность, то есть другая. - Когда вы исследуете позицию, фактически не нуждаясь в ней, это вряд ли "использование правильной функции для работы". Ясно, что намереваются оптимизировать микросекунды. (Разве вы не это процитировали?)
марио
1
@mario, но нет функции, единственной целью которой является проверка существования подстроки. Положение подстроки (если найден) свободно информацию , как только вы на самом деле его нашли. OTOH strstrделает больше, чем требуется, поэтому он медленнее.
Alnitak
@Alnitak: Имейте в виду, не новости. Похоже, вы очень непреклонно указываете на разницу в производительности, и только это. Это явный признак микрооптимизации. В профилировщике это не помешает . Что действительно важно, так это в удобочитаемости кода.
Марио
@mario на самом деле меня очень мало заботит производительность. Я очень забочусь о том, чтобы использовать правильную функцию для работы ;-)
Alnitak
0

strpos () определяет, где в стоге сена лежит конкретная иголка. stristr () проверяет, находится ли иголка где-нибудь в стоге сена

поэтому strpos () работает быстрее и потребляет меньше памяти

причина для strstr (): если ваша стрелка находится в начале строки, strpos возвращает 0 (поэтому необходимо проверить это с помощью === false)

Колба
источник
6
это полностью фиктивное объяснение - strstr()возвращает все до или после иглы, поэтому сначала нужно выполнить эквивалент, strpos() а затем создать эту подстроку . Вот где падает производительность.
Alnitak
-2

Я предпочитаю strstr()удобочитаемость и простоту кодирования .. strpos() !==false немного сбивает с толку ..

Т. Тодуа
источник
1
strstrслишком похож наstrtr
Мартиньш Бриедис
strstrтоже требует строгого сравнения Пример:('123450', '0')
Элвис