2009-03-06 19 views
105

Tiêu chuẩn PHP cách để kiểm tra xem một chuỗi $str kết thúc bằng một chuỗi con $test là:Thử nghiệm hiệu quả nhất cho dù chuỗi PHP kết thúc bằng một chuỗi khác là gì?

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

Đây có phải là cách nhanh nhất?

+2

tương tự: http://stackoverflow.com/questions/834303/php-startswith- và-endswith-chức năng – trante

+0

Bạn có thể tìm thấy ['s ($ str) -> endsWith ($ test)'] (https://github.com/delight-im/PHP-Str/blob/8fd0c608d5496d43adaa899642c1cce047e076dc/src/Str. php # L117) hoặc ['s ($ str) -> endsWithIgnoreCase ($ test)'] (https://github.com/delight-im/PHP-Str/blob/8fd0c608d5496d43adaa899642c1cce047e076dc/src/Str.php#L131) hữu ích, như được tìm thấy trong [thư viện độc lập này] (https://github.com/delight-im/PHP-Str). – caw

Trả lời

132

Điều Assaf đã nói là chính xác. Có một hàm dựng sẵn trong PHP để làm chính xác điều đó.

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

Nếu $test dài hơn $str PHP sẽ đưa ra một cảnh báo, vì vậy bạn cần phải kiểm tra cho rằng đầu tiên.

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

Đẹp. Nó có vẻ như so sánh tại chỗ sẽ nhanh hơn so với substr(), như Assaf chỉ ra. –

+2

Câu trả lời của mcrumley rất hay, nhưng nó nên sử dụng '===' thay vì '=='. '===' là nghiêm ngặt hơn và thường làm những gì bạn muốn, trong khi '==' có thể dẫn đến những bất ngờ khó chịu. Đoạn mã thứ ba của mcrumley là đúng, nhưng hai đoạn mã đầu tiên thì không. substr_compare() trả về false trong một số trường hợp lỗi. Trong PHP, false == 0, vì vậy các đoạn mã sẽ báo hiệu rằng chuỗi đã được tìm thấy. Với ===, điều này không xảy ra. –

+0

Tôi đã gặp một lỗi ngày hôm nay sẽ phá vỡ giải pháp mà bạn đã đưa ra từ PHP 5.5.11 trở đi. https://bugs.php.net/bug.php?id=67043 – user2180613

7

Tùy thuộc vào loại hiệu quả mà bạn quan tâm.

Phiên bản của bạn sử dụng nhiều bộ nhớ hơn do bản sao bổ sung từ việc sử dụng đế.

Một phiên bản thay thế có thể tìm kiếm chuỗi gốc cho lần xuất hiện cuối cùng của chuỗi con mà không tạo bản sao, nhưng có thể sẽ chậm hơn do thử nghiệm nhiều hơn.

Có lẽ cách hiệu quả nhất là làm vòng lặp char-by-char từ vị trí -sterlen (kiểm tra) cho đến cuối chuỗi và so sánh. Đó là số lượng tối thiểu so sánh bạn có thể hy vọng sẽ làm và hầu như không có bất kỳ bộ nhớ bổ sung nào được sử dụng.

4

Một cách khác là sử dụng các strrpos function:

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

Nhưng đó không phải là nhanh hơn.

0

Tôi nghĩ các chức năng ngược lại như strrchr() sẽ giúp bạn kết thúc chuỗi kết thúc nhanh nhất.

63

Phương pháp này là bộ nhớ đắt hơn một chút, nhưng nó là nhanh hơn:

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

này phù hợp nhất khi bạn biết chính xác những gì các kim là, vì vậy bạn có thể mã hóa cứng nó đảo ngược. Nếu bạn đảo ngược kim theo chương trình, nó sẽ trở nên chậm hơn so với phương pháp trước đó.

+0

Điều đó thật thông minh! –

+0

+1 cho độc đáo! –

+2

-1 Tôi nghiêm túc nghi ngờ điều này là nhanh hơn, và nó là khó khăn (mát mẻ nhưng không thường hữu ích). Nếu haystack * không * kết thúc bằng kim, 'stripos' sẽ lặp lại toàn bộ chuỗi trong trường hợp xấu nhất trong khi' substr_compare' sẽ so sánh với chiều dài của kim. Có, 'substr_compare' yêu cầu tính toán chiều dài của haystack (và kim nhỏ hơn nhiều), nhưng phương pháp này yêu cầu * và * sao chép nó đầy đủ, và có thể chuyển đổi toàn bộ thứ thành chữ thường để khởi động. –

7

Đây là một cách đơn giản để kiểm tra xem một chuỗi kết thúc với nhau, bằng cách cho strpos một bù đắp đúng nơi chuỗi nên được tìm thấy:

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

thẳng thắn, và tôi nghĩ rằng đây sẽ làm việc trong PHP 4.

2

tôi hy vọng rằng câu trả lời dưới đây có thể hiệu quả và cũng đơn giản:

$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'; 
-1

Đây là PHP thuần túy, mà không gọi chức năng bên ngoài s, ngoại trừ 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; 
} 
35
$endsWith = substr_compare($str, $test, -strlen($test)) === 0 

Negative bù đắp "bắt đầu tính từ khi kết thúc chuỗi".

+3

IMO là một trong những giải pháp tốt nhất từ ​​các giải pháp được cung cấp –

+4

Phải là câu trả lời được chấp nhận – FrancescoMM

+0

+200 nếu có thể. Thông tin chi tiết quan trọng ở đây là sử dụng độ dài phủ định sẽ là phần cuối của chuỗi. Bạn cũng có thể sử dụng substr với chiều dài -ve và làm một == với $ test. Các câu trả lời khác là người nghèo. – Nick

1

Không biết nếu điều này là nhanh hay không nhưng đối với một thử nghiệm đơn nhân vật, những công việc, quá:

(array_pop(str_split($string)) === $test) ? true : false; 
($string[strlen($string)-1] === $test) ? true : false; 
(strrev($string)[0] === $test) ? true : false; 
Các vấn đề liên quan