简体   繁体   English

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

[英]Checking for existence in a string with strpos

I've only ever seen developers use strict comparisons when they use strpos to check for the existence of a substring: 我只见过开发人员在使用strpos检查子字符串是否存在时使用严格的比较:

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

}

It occurred to me today that one could use is_numeric ins 今天我想到可以使用is_numeric ins

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

}

Is there a reason one would use one over the other (specifically in this use case)? 是否有一个理由会使用另一个理由(特别是在此用例中)?

If you think about it, the purpose of strpos is to return the position of the substring. 如果您考虑一下, strpos的目的是返回子字符串的位置 Only if it doesn't exist, will it return false. 仅当它不存在时,它才会返回false。 The position is a number . 该职位是一个数字 Thus, is_numeric is pretty qualified to be considered semantically. 因此, is_numeric非常适合在语义上考虑。

I've created a benchmark. 我已经创建了一个基准。 Case check by compare with false value always faster than check by is_numeric . check by compare with false value大小写check by compare with false value总是比check by is_numeric check by compare with false value大小写check by compare with false value更快。

// 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

I found this question searching for almost the same question, except my thought was to use is_int( ) not is_numeric( ) . 我发现这个问题正在搜索几乎相同的问题,除了我的想法是使用is_int( )而不是is_numeric( ) I couldn't really understand the benchmark that was posted so I made my own. 我不太了解所发布的基准测试,因此我自己制定了基准测试。 In short, is_numeric( ) is a hair slower than !== false , and is_int( ) is a hair faster. 简而言之, is_numeric( )的头发速度比!== false慢,而is_int( )的头发速度更快。 Personally, I find it more readable than !== false not less, so I'll probably switch to it. 就个人而言,我发现它比!== false更易读,所以我可能会改用它。

This was done under php v7.1.23 这是在php v7.1.23下完成的

Results: 结果:

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

From the code: 从代码:

$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";

Since strpos returns either integer or boolean false it's okay to use is_numeric . 由于strpos返回整数或布尔值false,因此可以使用is_numeric
The question is: 问题是:
What is more idiomatic and autodocumented/self-descriptive , using is_numeric or comparing return value to boolean? 使用is_numeric或将返回值与布尔值进行比较,还有什么更惯用自动记录/自我描述 IMO, comparing to boolean false is much more intuitive: IMO,与布尔假相比,更加直观:

$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";

Also, strpos(...) !== false is overused because it's what PHP documentation suggests. 另外, strpos(...) !== false被过度使用,因为这是PHP文档所建议的。 Thus it has become conventional. 因此,这已成为常规。

  1. Using strpos in this context is for is greater speed over preg_match, using is_numeric on top of it is negating this speed advantage by adding more overhead. 在这种情况下使用strpos的目的是要比preg_match具有更高的速度,在其上使用is_numeric可以通过增加更多开销来抵消这种速度优势。
  2. Using another function just to separate false from the rest makes no sense, better just use !== false 仅使用另一个函数将false与其余函数分开是没有意义的,最好仅使用!== false

There is no reason why would anybody use is_numeric, but it will work, only slower. 没有任何人会使用is_numeric的理由,但是它将起作用,只是速度较慢。

About strpos vs preg_match: preg_match() vs strpos() for match finding? 关于strpos vs preg_match: preg_match()vs strpos()用于匹配查找? and which is the fast process strpos()/stripos() or preg_match() in php 这是PHP中的快速过程strpos()/ stripos()或preg_match()

You are right, is_numeric works with strpos . 没错, is_numeric可与strpos But this can make the code tricky, hence lowering code readability. 但这会使代码变得棘手,从而降低了代码的可读性。

Have in mind that although this may seems obvious to you, you are making another programmer that reads your code think in a lot of things: 请记住,尽管这对您来说似乎很明显,但是您正在使另一个读取您的代码的程序员在很多方面都进行了思考:

  1. Does the haystack contains the needle? 干草堆中是否装有针头?
  2. Which is the position of the needle in the haystack? 大海捞针的位置在哪里?
  3. What type of value does strpos returns? strpos返回什么类型的值?
  4. Is the returned value of strpos a number in this case? 在这种情况下,strpos的返回值是数字吗?

And PHP can be quite a tricky language by itself, take a look at this examples: 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, the best option is using ===false and ==!false comparisons, like explained in the php documentation for strpos : 恕我直言,最好的选择是使用===false==!false比较,就像在strpos的php文档中解释的那样:

Warning This function may return Boolean FALSE , but may also return a non-Boolean value which evaluates to FALSE. 警告此函数可能返回布尔值FALSE ,但也可能返回非布尔值,其值为FALSE。 Please read the section on Booleans for more information. 请阅读布尔值部分以获取更多信息。 Use the === operator for testing the return value of this function. 使用===运算符测试此函数的返回值。

PD: For a better definition of "truthy" take a look at this post . PD:有关“真实”的更好定义,请看一下这篇文章

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM