PHP字符串是否以另一个字符串结尾的最有效测试是什么?


125

测试字符串是否$str以子字符串结尾的标准PHP方法$test是:

$endsWith = substr( $str, -strlen( $test ) ) == $test

这是最快的方法吗?



您可能会发现s($str)->endsWith($test)s($str)->endsWithIgnoreCase($test)有所帮助,如在此独立库中找到的那样。
caw 2016年

Answers:


152

阿萨夫所说的是正确的。PHP中有一个内置函数可以做到这一点。

substr_compare($str, $test, strlen($str)-strlen($test), strlen($test)) === 0;

如果$test$strPHP 长,则会发出警告,因此您需要首先进行检查。

function endswith($string, $test) {
    $strlen = strlen($string);
    $testlen = strlen($test);
    if ($testlen > $strlen) return false;
    return substr_compare($string, $test, $strlen - $testlen, $testlen) === 0;
}

真好 正如Assaf指出的那样,就地比较似乎确实比substr()更快。
杰森·科恩,2009年

2
mcrumley的答案很酷,但应使用'==='而不是'=='。'==='更严格,通常会按照您的要求进行,而'=='可能会导致令人讨厌的意外。mcrumley的第三个代码段是正确的,但前两个不是。在某些错误情况下,substr_compare()返回false。在PHP中,false == 0,因此代码段将表明已找到该字符串。对于===,这不会发生。
jcsahnwaldt恢复莫妮卡

1
今天,我遇到了一个错误,该错误将破坏您从PHP 5.5.11起提供的解决方案。bugs.php.net/bug.php?id=67043
user2180613

3个函数调用开销并不能使其最快。
Thanh Trung,

66

此方法稍微有点消耗内存,但速度更快:

stripos(strrev($haystack), $reversed_needle) === 0;

当您确切知道针是什么时,这是最好的,因此您可以将其反向硬编码。如果以编程方式反转针,它会比以前的方法慢。


2
-1我严重怀疑这会更快,并且棘手(很酷,但通常没有帮助)。如果干草堆没有以针头结束,stripos则在最坏的情况下将迭代整个字符串,而substr_compare最多只能比较针头的长度。是的,substr_compare需要计算草堆(和更小的针)的长度,但这种方法需要复制它满了,整个事情可能转换成小写启动。
David Harkness

很酷的方法,但是在许多情况下效率很低(如答案中提到的那样)!对于奇怪的创造力并证明总是有更多的方法来做您可能想像的相同事情,这仍然是一种赞扬。干杯!
Fr0zenFyr

1
我进行了测试,发现这种方法比接受的答案要快。即使干草堆和针头都可以快速翻转,也更快。
Shumoapp

@DavidHarkness您是否进行了测试以查看是否值得怀疑?
弥敦道

@Nathan不,因为substr_compare()效果很好,所以不值得花时间进行基准测试。
David Harkness

61
$endsWith = substr_compare( $str, $test, -strlen( $test ) ) === 0

负偏移量“从字符串末尾开始计数”。


3
IMO是提供的解决方案中最好的之一
Roman Podlinov

如果可以的话,+ 200。此处的关键见解是,使用负数长度将获取字符串的结尾部分。您还可以将substr与-ve长度一起使用,并对$ test进行==。其他答案很差。
尼克

11

这是检查一个字符串是否以另一字符串结尾的简单方法,方法是strpos在应该找到该字符串的位置给出偏移量:

function stringEndsWith($whole, $end)
{
    return (strpos($whole, $end, strlen($whole) - strlen($end)) !== false);
}

简单来说,我认为这将在PHP 4中起作用。


8

这取决于您关心哪种效率。

由于使用substr会产生额外的副本,因此您的版本使用更多的内存。

替代版本可能会在原始字符串中搜索子字符串的最后一次出现而没有进行复制,但是由于进行了更多的测试,因此可能会变慢。

可能最有效的方法是从-sterlen(test)位置逐字符循环直到字符串的末尾并进行比较。那是您可以希望进行的最小比较,并且几乎没有使用任何额外的内存。


5

另一种方法是使用该strrpos函数

strrpos($str, $test) == strlen($str) - strlen($test)

但这并没有更快。


3

我希望以下答案可能有效且简单:

$content = "The main string to search";
$search = "search";
//For compare the begining string with case insensitive. 
if(stripos($content, $search) === 0) echo 'Yes';
else echo 'No';

//For compare the begining string with case sensitive. 
if(strpos($content, $search) === 0) echo 'Yes';
else echo 'No';

//For compare the ending string with case insensitive. 
if(stripos(strrev($content), strrev($search)) === 0) echo 'Yes';
else echo 'No';

//For compare the ending string with case sensitive. 
if(strpos(strrev($content), strrev($search)) === 0) echo 'Yes';
else echo 'No';

2

不知道这是否快速,但是对于单个字符测试,这些也可以:

(array_pop(str_split($string)) === $test) ? true : false;
($string[strlen($string)-1] === $test) ? true : false;
(strrev($string)[0] === $test) ? true : false;


0

我在想像strrchr()这样的反向函数将帮助您最快地匹配字符串的结尾。


0

这是纯PHP,不调用外部函数(strlen除外)。

function endsWith ($ends, $string)
{
    $strLength = strlen ($string);
    $endsLength = strlen ($ends);
    for ($i = 0; $i < $endsLength; $i++)
    {
        if ($string [$strLength - $i - 1] !== $ends [$i])
            return false;
    }
    return true;
}

0

对于单字符针:

if (@strrev($haystack)[0] == $needle) {
   // yes, it ends...
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.