Проверка существования в строке с помощью strpos


Я только когда-либо видел, чтобы разработчики использовали строгие сравнения, когда они используют strpos для проверки существования подстроки:

if (strpos($haystack,$needle) !== false) {

}

Сегодня мне пришло в голову, что один может использовать is_numeric ins

if (is_numeric(strpos($haystack,$needle))) {

}
Есть ли причина, по которой один будет использовать один над другим (особенно в этом случае использования)?

Если подумать, то цель strpos состоит в том, чтобы вернуть позицию подстроки. Только если он не существует, он возвратит ложь. Позиция число . Таким образом, is_numeric достаточно квалифицирован, чтобы быть рассмотренным семантически.

4 2

4 ответа:

Я создал эталон. Случай check by compare with false value всегда быстрее, чем check by is_numeric.

// Init a big string array

for($i = 0; $i < 10000; $i++){
$str[] = 'a'.rand().'b'.rand();
}

// Case comparing with false value
$time1 = microtime(true);
foreach($str as $st){
$res[] = strpos($st,rand(0, count(array('b', 'c')) - 1 )) !== false;
}
$time2 = microtime(true);

echo $time2-$time1.'<br/>';

// Case 'is_numeric'
$time3 = microtime(true);
foreach($str as $st){
$res[] = is_numeric(strpos($st,rand(0, count(array('b', 'c')) - 1 )));
}
$time4 = microtime(true);
echo $time4-$time3;


//Time 1: 
//0.018877029418945 
//0.020556926727295

//Time 2:
//0.016352891921997
//0.016934871673584

//Time 3:
//0.0121009349823
//0.01330304145813

//Time 4:
//0.017507076263428
//0.01904296875

Поскольку strpos возвращает либо целое число, либо логическое значение false, можно использовать is_numeric.
Вопрос в следующем:
Что является более идиоматическим и автодокументированным / самоописательным , использующим is_numeric или сравнивающим возвращаемое значение с булевым? IMO, по сравнению с boolean false, гораздо более интуитивно понятен:

$string = 'new object';
$found = strpos($string,'new');

echo (is_numeric($found)) ? 'found' : 'not found';
echo "\n";
# much better
echo ($found !== false)   ? 'found' : 'not found';
echo "\n";

Также, strpos(...) !== false используется слишком часто, потому что это то, что предполагает документация PHP. Таким образом, оно стало общепринятым.

  1. Использование strpos в этом контексте является для is большей скоростью по сравнению с preg_match, использование is_numeric поверх него отрицает это преимущество скорости, добавляя больше накладных расходов.
  2. Использование другой функции только для отделения false от остальных не имеет смысла, лучше просто использовать != = false

Нет никаких причин, почему кто-то будет использовать is_numeric, но он будет работать, только медленнее.

О strpos vs preg_match: preg_match () vs strpos () для поиска совпадений? и который является быстрый процесс strpos()/stripos () или preg_match () в php

Вы правы, is_numeric работает с strpos. Но это может сделать код сложным, следовательно, снижая читаемость кода.

Имейте в виду, что, хотя это может показаться вам очевидным, вы заставляете другого программиста, который читает ваш код, думать о многих вещах:
    Содержит ли стог сена иголку? Каково положение иглы в стоге сена?
  1. Какой тип значения возвращает strpos?
  2. является ли возвращаемое значение strpos числом в этом случае?

И PHP может быть довольно сложным языком сам по себе, взгляните на эти примеры:

if (strpos("needle in a haystack","needle")!==false) {
    echo "Needle found!<br>";
} else {
    echo "nothing found<br>";
}

if (is_numeric(strpos("needle in a haystack","needle"))) {
    echo "Needle found!<br>";
} else {
    echo "nothing found<br>";
}

if (is_int(strpos("needle in a haystack","needle"))) {
    echo "Needle found!<br>";
} else {
    echo "nothing found<br>";
}

// This doesn't work since 0 == false is true
if (strpos("needle in a haystack","needle")!=false) {
    echo "Needle found!<br>";
} else {
    echo "nothing found<br>";
}

// But this works since "haystack" position is not 0
if (strpos("needle in a haystack","haystack")!=false) {
    echo "Haystack found!<br>";
} else {
    echo "nothing found<br>";
}

// This doesn't work also because "needle" is at 0, and 0 is not a truthy value
if (strpos("needle in a haystack","needle")) {
    echo "Needle found!<br>";
} else {
    echo "nothing found<br>";
}

// But this works again since "haystack" position is not 0, and any int that's not 0 is truthy
if (strpos("needle in a haystack","haystack")) {
    echo "Haystack found!<br>";
} else {
    echo "nothing found<br>";
}

Имхо, лучшим вариантом является использование сравнений ===false и ==!false, как описано в документации php для strpos :

Предупреждение Эта функция может возвращать логическое ложные, но может также возвращает не булево значение, которое принимает значение false. Пожалуйста, прочитайте раздел о логических значениях для получения дополнительной информации. Используйте оператор === для проверки возвращаемого значения этой функции.

PD: для лучшего определения "правдивости" взгляните на этот пост.