Tes apa yang paling efisien untuk mengetahui apakah string PHP diakhiri dengan string lain?

Jawaban:

152

Apa yang dikatakan Assaf benar. Ada fungsi bawaan di PHP untuk melakukan hal itu.

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

Jika $testlebih panjang dari $strPHP akan memberikan peringatan, jadi Anda perlu memeriksanya terlebih dahulu.

function endswith($string, $test) {
    $strlen = strlen($string);
    $testlen = strlen($test);
    if ($testlen > $strlen) return false;
    return substr_compare($string, $test, $strlen - $testlen, $testlen) === 0;
}
mcrumley.dll
sumber
Bagus. Tampaknya membandingkan di tempat akan lebih cepat daripada substr (), seperti yang ditunjukkan Assaf.
Jason Cohen
2
Jawaban mcrumley adalah keren, tetapi seharusnya menggunakan '===' daripada '=='. '===' lebih ketat dan biasanya melakukan apa yang Anda inginkan, sementara '==' dapat menyebabkan kejutan yang tidak menyenangkan. Potongan kode ketiga mcrumley benar, tetapi dua yang pertama tidak. substr_compare () mengembalikan nilai salah dalam beberapa kasus kesalahan. Di PHP, false == 0, jadi potongan kode akan memberi sinyal bahwa string telah ditemukan. Dengan ===, ini tidak terjadi.
jcsahnwaldt Memulihkan Monica
1
Saya mengalami bug hari ini yang akan merusak solusi yang telah Anda berikan dari PHP 5.5.11 dan seterusnya. bugs.php.net/bug.php?id=67043
user2180613
3 fungsi panggilan overhead tidak membuatnya tercepat.
Thanh Trung
66

Metode ini sedikit lebih mahal untuk memori, tetapi lebih cepat:

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

Ini paling baik ketika Anda tahu persis apa jarum itu, sehingga Anda dapat membuat kode keras untuk membalikkannya. Jika Anda membalik jarum secara terprogram, ini menjadi lebih lambat dari metode sebelumnya.

jscheel.dll
sumber
2
-1 Saya benar-benar meragukan ini lebih cepat, dan ini rumit (keren tapi biasanya tidak membantu). Jika tumpukan jerami tidak berakhir dengan jarum, striposakan mengulangi seluruh string dalam kasus terburuk sedangkan substr_compareakan membandingkan paling banyak panjang jarum. Ya, substr_comparememerlukan penghitungan panjang tumpukan jerami (dan jarum yang jauh lebih kecil), tetapi metode ini memerlukannya dan menyalinnya secara penuh, dan mungkin mengubah semuanya menjadi huruf kecil untuk boot.
David Harkness
pendekatan yang keren tetapi tidak efisien (seperti yang disebutkan dalam jawaban itu sendiri) dalam banyak kasus! Masih merupakan suara positif untuk menjadi kreatif yang aneh dan menunjukkan bahwa selalu ada lebih banyak cara untuk melakukan hal yang sama yang pernah Anda bayangkan. Bersulang!
Fr0zenFyr
1
Saya menguji dan menemukan metode ini lebih cepat daripada jawaban yang diterima. Bahkan jika tumpukan jerami dan jarum dibalik dengan cepat, itu lebih cepat.
Shumoapp
@DavidHarkness Apakah Anda menguji untuk melihat apakah keraguan Anda benar?
Nathan
@Nathan Tidak, ini tidak sepadan dengan waktu untuk melakukan benchmark karena substr_compare()berfungsi dengan baik.
David Harkness
61
$endsWith = substr_compare( $str, $test, -strlen( $test ) ) === 0

Offset negatif "mulai menghitung dari akhir string".

Alexander Yanovets
sumber
3
IMO itu salah satu yang terbaik dari solusi yang disediakan
Roman Podlinov
200 jika saya bisa. Wawasan utama di sini adalah bahwa menggunakan panjang negatif mendapatkan bagian akhir dari string. Anda juga dapat menggunakan substr dengan panjang -ve dan melakukan tes == terhadap $. Jawaban lainnya buruk.
Nick
11

Berikut cara sederhana untuk memeriksa apakah satu string diakhiri dengan yang lain, dengan memberikan strposoffset tepat di tempat string tersebut harus ditemukan:

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

Mudah, dan saya pikir ini akan berfungsi di PHP 4.

Patrick Smith
sumber
8

Itu tergantung pada efisiensi seperti apa yang Anda pedulikan.

Versi Anda menggunakan lebih banyak memori karena salinan ekstra dari penggunaan media.

Versi alternatif mungkin mencari string asli untuk kemunculan terakhir substring tanpa membuat salinan, tetapi mungkin akan lebih lambat karena pengujian lebih lanjut.

Mungkin cara yang paling efisien adalah dengan melakukan loop char-by-char dari posisi -sterlen (test) sampai akhir string dan bandingkan. Itulah jumlah minimal perbandingan yang dapat Anda lakukan dan hampir tidak ada memori tambahan yang digunakan.

Assaf Lavie
sumber
5

Cara lain adalah dengan menggunakan strrposfungsi :

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

Tapi itu tidak lebih cepat.

Gumbo
sumber
3

Saya berharap jawaban di bawah ini bisa efisien dan juga sederhana:

$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';
Srinivasan.S
sumber
2

Tidak tahu apakah ini cepat atau tidak tetapi untuk tes karakter tunggal, ini juga berfungsi:

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

cara termudah untuk memeriksanya melalui ekspresi reguler

misalnya untuk memeriksa apakah email yang diberikan adalah gmail:

echo (preg_match("/@gmail\.com$/","[email protected]"))?'true':'false';
Biskrem Muhammad
sumber
0

Saya berpikir fungsi kebalikan seperti strrchr () akan membantu Anda mencocokkan akhir string paling cepat.

tkotitan
sumber
0

Ini adalah PHP murni, tanpa memanggil fungsi eksternal, kecuali untuk 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;
}
Xesau
sumber
0

untuk jarum satu karakter:

if (@strrev($haystack)[0] == $needle) {
   // yes, it ends...
}
kabantejay
sumber