簡體   English   中英

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

[英]Checking for existence in a string with strpos

我只見過開發人員在使用strpos檢查子字符串是否存在時使用嚴格的比較:

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

}

今天我想到可以使用is_numeric ins

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

}

是否有一個理由會使用另一個理由(特別是在此用例中)?

如果您考慮一下, strpos的目的是返回子字符串的位置 僅當它不存在時,它才會返回false。 該職位是一個數字 因此, 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

我發現這個問題正在搜索幾乎相同的問題,除了我的想法是使用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";

由於strpos返回整數或布爾值false,因此可以使用is_numeric
問題是:
使用is_numeric或將返回值與布爾值進行比較,還有什么更慣用自動記錄/自我描述 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";

另外, strpos(...) !== false被過度使用,因為這是PHP文檔所建議的。 因此,這已成為常規。

  1. 在這種情況下使用strpos的目的是要比preg_match具有更高的速度,在其上使用is_numeric可以通過增加更多開銷來抵消這種速度優勢。
  2. 僅使用另一個函數將false與其余函數分開是沒有意義的,最好僅使用!== false

沒有任何人會使用is_numeric的理由,但是它將起作用,只是速度較慢。

關於strpos vs preg_match: preg_match()vs strpos()用於匹配查找? 這是PHP中的快速過程strpos()/ stripos()或preg_match()

沒錯, is_numeric可與strpos 但這會使代碼變得棘手,從而降低了代碼的可讀性。

請記住,盡管這對您來說似乎很明顯,但是您正在使另一個讀取您的代碼的程序員在很多方面都進行了思考:

  1. 干草堆中是否裝有針頭?
  2. 大海撈針的位置在哪里?
  3. strpos返回什么類型的值?
  4. 在這種情況下,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比較,就像在strpos的php文檔中解釋的那樣:

警告此函數可能返回布爾值FALSE ,但也可能返回非布爾值,其值為FALSE。 請閱讀布爾值部分以獲取更多信息。 使用===運算符測試此函數的返回值。

PD:有關“真實”的更好定義,請看一下這篇文章

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM