views:

4037

answers:

7

The standard PHP way to test whether a string $str ends with a substring $test is:

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

Is this the fastest way?

+3  A: 

It depends on which sort of efficiency you care about.

Your version uses more memory due to the extra copy from the use of substr.

An alternative version might search the original string for the last occurrence of the substring without making a copy, but would probably be slower due to more testing.

Probably the most efficient way is to do loop char-by-char from the -sterlen(test) position till the end of the string and compare. That's the minimal amount of comparisons you can hope to do and there's hardly any extra memory used.

Assaf Lavie
+2  A: 

Another way would be to use the strrpos function:

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

But that’s not faster.

Gumbo
+9  A: 

What Assaf said is correct. There is a built in function in PHP to do exactly that.

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

If you are not using PHP 5.1 or higher you will need to calculate the offset a little differently because you cannot use a negative offset.

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

If the $test is longer than $str PHP will give a warning, so you need to check for that first.

function endswith($string, $test) {
    $strlen = strlen($string);
    $testlen = strlen($test);
    if ($testlen > $strlen) return false;
    return substr_compare($string, $test, -$testlen) === 0;
}
mcrumley
Nice. It does seem like comparing in-place would be faster than substr(), as Assaf pointed out.
Jason Cohen
A: 

I'm thinking the reverse functions like strrchr() would help you match the end of the string the fastest.

tkotitan
A: 

mcrumley's answer is cool, but it should use '===' instead of '=='. '===' is more strict and usually does what you want, while '==' can lead to nasty surprises.

mcrumley's third code snippet is correct, but the first two aren't. substr_compare() returns false in some error cases. In PHP, false == 0, so the code snippets would signal that the string has been found. With ===, this doesn't happen.

Christopher Sahnwaldt
A: 

This method is a tiny bit more memory-expensive, but it is faster:

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

This is best when you know exactly what the needle is, so you can hard-code it reversed. If you reverse the needle programatically, it becomes slower than the earlier method.

jscheel
A: 

I still prefer some good ol' /string$/!

BIllium
regex is overkill for this problem - especially since he asked for an efficient one.
efritz
Not that it wouldn't work >_>
efritz