使用strpos检查字符串是否存在

时间:2016-01-15 01:20:19

标签: php strpos

我只看到开发人员在使用strpos检查子字符串是否存在时使用严格的比较:

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

}

今天我发现一个可以使用is_numeric ins

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

}

有没有理由让一个人使用另一个(特别是在这个用例中)?

如果您考虑一下,strpos的目的是返回子字符串的位置。只有它不存在,才会返回false。该位置是数字。因此,is_numeric非常有资格被认为是语义上的。

5 个答案:

答案 0 :(得分:3)

我创建了一个基准。案例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

答案 1 :(得分:1)

由于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文档建议的内容。因此它已成为传统。

答案 2 :(得分:1)

我发现这个问题在搜索几乎相同的问题,除了我的想法是使用is_int( )而不是is_numeric( )。我不太了解所发布的基准测试,因此我自己制定了基准测试。简而言之,is_numeric( )的头发比!== false的头发慢,而is_int( )的头发则更快。就个人而言,我发现它比!== false更具可读性,所以我可能会改用它。

这是在php v7.1.23下完成的

结果:

0.7900s for '!== false' with hits
4.5137s for '!== false' with misses

0.9297s for 'is_numeric' with hits
4.7509s for 'is_numeric' with misses

0.6391s for 'is_int' with hits
4.4862s for 'is_int' with misses

从代码中:

$n_times = 10000000;
$haystack_hit = "  Certificate Name: example.com";
$heystack_miss = "Found the following certs:";
$needle = "Certificate Name:";

$start = microtime(true);
for($i = 0; $i < $n_times; $i++)
    {
    if (strpos($haystack_hit,$needle) !== false)
        { }
    }
$end = microtime(true) - $start;
echo "\n" . round($end,4) . "s for '!== false' with hits\n";

$start = microtime(true);
for($i = 0; $i < $n_times; $i++)
    {
    if (strpos($haystack_miss,$needle) !== false)
        { }
    }
$end = microtime(true) - $start;
echo round($end,4) . "s for '!== false' with misses\n\n";

// -----

$start = microtime(true);
for($i = 0; $i < $n_times; $i++)
    {
    if ( is_numeric(strpos($haystack_hit,$needle)) )
        { }
    }
$end = microtime(true) - $start;
echo round($end,4) . "s for 'is_numeric' with hits\n";

$start = microtime(true);
for($i = 0; $i < $n_times; $i++)
    {
    if ( is_numeric(strpos($haystack_miss,$needle)) )
        { }
    }
$end = microtime(true) - $start;
echo round($end,4) . "s for 'is_numeric' with misses\n\n";

// -----

$start = microtime(true);
for($i = 0; $i < $n_times; $i++)
    {
    if ( is_int(strpos($haystack_hit,$needle)) )
        { }
    }
$end = microtime(true) - $start;
echo round($end,4) . "s for 'is_int' with hits\n";

$start = microtime(true);
for($i = 0; $i < $n_times; $i++)
    {
    if ( is_int(strpos($haystack_miss,$needle)) )
        { }
    }
$end = microtime(true) - $start;
echo round($end,4) . "s for 'is_int' with misses\n";

答案 3 :(得分:0)

  1. 在此上下文中使用strpos是为了比preg_match更快的速度,在它之上使用is_numeric通过增加更多开销来否定这种速度优势。
  2. 使用另一个函数只是为了将false与其他函数分开是没有意义的,最好只使用!== false
  3. 没有理由为什么有人会使用is_numeric,但它会起作用,只会慢一些。

    关于strpos vs preg_match: preg_match() vs strpos() for match finding?which is the fast process strpos()/stripos() or preg_match() in php

答案 4 :(得分:0)

您是对的,is_numeric适用于strpos。但这会使代码变得棘手,从而降低了代码的可读性。

请记住,虽然这对您来说似乎很明显,但是您正在制作另一个程序员来阅读您的代码,并考虑很多事情:

  1. 大海捞针是否包含针头?
  2. 针在大海捞针中的位置是什么?
  3. strpos返回什么类型的值?
  4. 在这种情况下,strpos的返回值是否为数字?
  5. 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>";
    }
    

    Imho,最好的选择是使用===false==!false比较,如the php documentation for strpos中所述:

      

    警告   此函数可能返回布尔值 FALSE ,但也可能返回非布尔值,其值为FALSE。有关更多信息,请阅读有关布尔值的部分。使用===运算符测试此函数的返回值。

    PD:为了更好地定义&#34; truthy&#34;看看this post