2009-03-06 7 views
105

$str dizesinin $test alt dizesiyle bitip bitmediğini sınamak için standart PHP yolu:Bir PHP dizgisinin başka bir dizeyle bitip bitmediğinin en etkili testi nedir?

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

Bu en hızlı yol mu?

+2

Benzer: http://stackoverflow.com/questions/834303/php-startswith- ve-endswith işlevleri – trante

+0

['s ($ str) -> endsWith ($ test)'] (https://github.com/delight-im/PHP-Str/blob/8fd0c608d5496d43adaa899642c1cce047e076dc/src/Str. php # L117) veya ['s ($ str) -> endsWithIgnoreCase ($ test)'] (https://github.com/delight-im/PHP-Str/blob/8fd0c608d5496d43adaa899642c1cce047e076dc/src/Str.php#L131) Bu bağımsız kütüphanede (https://github.com/delight-im/PHP-Str) olduğu gibi yararlıdır. – caw

cevap

132

Assaf'ın söylediği doğrudur. Tam olarak bunu yapmak için PHP'de yerleşik bir işlev var.

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

$test öncelikle bunun için kontrol etmeniz gerekir, böylece bir uyarı verecektir uzun $str PHP daha uzunsa.

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

Güzel. Assaf'ın işaret ettiği gibi, yerinde karşılaştırmanın substr() 'dan daha hızlı olacağını düşünüyor. –

+2

mcrumley'nin cevabı harika, ancak '==' yerine '===' kullanmalısınız. '===' daha katı ve genellikle istediğiniz şeyi yapar, '==' ise kötü sürprizlere yol açabilir. mcrumley'nin üçüncü kod snippet'i doğru, ancak ilk ikisi değil. substr_compare() bazı hata durumlarında false değerini döndürür. PHP'de false == 0, böylece kod parçacıkları dizenin bulunduğunu işaret ederdi. === ile, bu olmaz. –

+0

Bugün PHP 5.5.11 ve sonrasında verdiğiniz çözümü kesecek bir hata yaptım. https://bugs.php.net/bug.php?id=67043 – user2180613

7

Ne tür bir verimlilikle ilgilendiğinize bağlıdır.

Sürümünüzü, alt sayfaların kullanımıyla ilgili ek kopyalar nedeniyle daha fazla bellek kullanır.

Alternatif bir sürüm, bir kopyasını almadan alt dizinin son oluşumu için orijinal dizeyi arayabilir, ancak daha fazla sınama nedeniyle muhtemelen daha yavaş olabilir.

Muhtemelen en etkili yol, dizinin sonuna kadar -sterlen (test) konumundan döngü char-by-char yapmak ve karşılaştırmaktır. Yapacağınız çok az karşılaştırma oranı var ve kullanılan fazla bellek yok.

4

bir başka yolu strrpos function kullanmak olacaktır:

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

Ama bu değil hızlı.

0

Ben strrchr gibi ters fonksiyonları düşünüyorum() Eğer dize en hızlı sonunu eşleştirmeye yardımcı olacaktır.

63

Bu yöntem bir nebze daha bellek-pahalı, ama daha hızlı şudur: İğne tam olarak ne olduğunu ne zaman sabit kod ters böylece

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

Bu, en iyisidir. İğneyi programatik olarak tersine çevirirseniz, önceki yöntemden daha yavaş olur.

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

Kolay ve bu PHP 4'te çalışacağız düşünüyorum:

+0

Bu sadece çok akıllı! Özgünlük için –

+0

+1! –

+2

-1 Bunun daha hızlı olduğundan şüphe duyuyorum ve bu zor (havalı ama genelde yararlı değil). Samanlık * iğne ile bitmezse, 'stripos' en kötü durumda tüm dizgeyi yineler, 'substr_compare' ise iğnenin uzunluğunu karşılaştırır. Evet, 'substr_compare', samanlık uzunluğunun (ve çok daha küçük iğnenin) hesaplanmasını gerektirir, ancak bu yöntem, * ve * tam olarak kopyalamayı ve muhtemelen tüm şeyi önyüklemek için küçük harfe dönüştürmeyi gerektirir. –

7

İşte dize bulunmalıdır nerede bir hak ofset strpos vererek, tek dize başka biter olup olmadığını kontrol etmek için basit bir yol.

2

aşağıda cevap verimli ve aynı zamanda basit olabileceğini umut:

$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

Bu saf PHP olan dış işlevini çağırarak olmadan s, strlen hariç. Olumsuz

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 

"dizesinin sonundan sayım başlar" ofset.

+3

IMO, sunulan çözümlerden en iyilerden biri –

+4

Kabul edebiliyorsam, – FrancescoMM

+0

+200 kabul etmeliyim. Buradaki ana fikir, negatif uzunluk kullanılması dizenin son kısmını almasıdır. Ayrıca, substr değerini -ve uzunluğunda kullanabilir ve $ = $ testine karşı == Diğer cevaplar zayıf. – Nick

1

bu hızlı olup olmadığını bilmek ama çok tek bir karakter testi, bu iş için yapmayın:

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