Який метод є кращим strstr або strpos?


84

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


2
орієнтовний показник, який ви згадали, проти substr не strstr
Flask

Відповіді:


125

З онлайн-посібника PHP :

Якщо ви хочете лише визначити, чи трапляється певна голка в копиці сіна, strpos() натомість використовуйте швидшу та менш інтенсивну пам’ять .


13
+1, Ви можете використовувати strpos або stripos. і не забудьте перевірити попередження на php-документі про використання === FALSE;
fedmich

7
Докладніше про коментар Федміча: Я завжди використовую if(strpos($haystack,$needle) !== false) { // do something }, ніколи if(strpos($haystack,$needle)) { // do bad things }. strposповерне 0, якщо a $needleзнаходиться на самому початку $haystack, а 0 вважається рівним false. (0 == false)оцінює як істинне. (0 === false)оцінює як 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().

Сподіваюсь, цей тест комусь був корисний.


3
Хоча цей орієнтир корисний, він не вимірює споживання пам'яті, а також не враховує довгі рядки, такі як кбайти або мегабайти.

А? @ user133408 Довгі рядки та більші байтові рядки можуть зайняти навіть більше часу.
NiCk Newman

7

Багато розробників використовують strposдля цілей мікрооптимізації .

Використання strstrтакож працює лише в тому випадку, якщо отриманий рядок не може бути інтерпретований як хибний у логічному контексті.


11
Це не мікрооптимізація, це називається використанням відповідної функції для роботи . Якщо я хочу позицію рядка, я телефоную strpos(). Якщо я хотів підрядок після цієї позиції, я телефоную strstr().
Alnitak

1
@Alnitak: Те, що я говорив. Якщо ви хочете перевірити наявність рядка, тоді для цього є функція. Якщо вам справді потрібна посада, то є інша. - Коли ви зондуєте цю посаду, не потребуючи її, то це навряд чи "використовує правильну функцію для роботи". Намір явно полягає в оптимізації мікросекунд. (Чи не це ви цитували?)
Маріо

1
@mario, але немає функції, єдиною метою якої є перевірка, чи існує підрядок. Положення підрядка (якщо знайдений) вільно інформацію , як тільки ви на самому справі його знайшли. OTOH, strstrробить більше, ніж потрібно, саме тому це повільніше.
Alnitak

@Alnitak: Майте на увазі, а не новини. Ви здаєтесь дуже непохитними щодо вказівки на різницю в продуктивності, і лише це. Це свідчить про мікрооптимізацію. Це не робить промаху в профілі . Дещо впливає на читаність коду.
Маріо

@mario насправді я б дуже дбав про продуктивність. Я дуже дбаю про те, щоб використовувати потрібну функцію для роботи ;-)
Альнітак,

0

strpos () визначає, де в копиці сіна лежить певна голка. stristr () перевіряє, чи знаходиться голка в копиці сіна

тому strpos () є швидшим і менш споживає пам'ять

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


6
це абсолютно неправдиве пояснення - strstr()повертає все до або після голки, тому спочатку потрібно виконати еквівалент, strpos() а потім створити цю підрядок . Ось де хіт продуктивності.
Alnitak

-2

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


1
strstrзанадто схоже наstrtr
Mārtiņš Briedis

strstrпотрібне суворе порівняння. Приклад:('123450', '0')
Елвіс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.